I am trying to set up visual regression testing for react-chartjs-2 components with React Testing library. However, all of the snapshots that are being generated are blank, but the component renders properly in the browser.
This is what I'm currently testing. I basically combined this blog post example with the pie chart example from react-chartjs-2.
import React from 'react';
import {generateImage, debug} from 'jsdom-screenshot';
import {render} from '#testing-library/react';
import {Pie} from "react-chartjs-2";
it('has no visual regressions', async () => {
window.ResizeObserver =
window.ResizeObserver ||
jest.fn().mockImplementation(() => ({
disconnect: jest.fn(),
observe: jest.fn(),
unobserve: jest.fn(),
}));
const data = {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [
{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)',
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)',
],
borderWidth: 1,
},
],
};
render(<div><Pie data={data}/></div>)
expect(await generateImage()).toMatchImageSnapshot();
});
I am wondering if it's a timing issue. Running debug() before the expect shows a canvas with 0 width and height:
<canvas
height="0"
role="img"
style="display: block; box-sizing: border-box; height: 0px; width: 0px;"
width="0"
/>
The charting library you're using, react-chartjs-2, wraps chart.js, which relies on the canvas element to render charts to the screen. It's important to note that canvas contents are not part of the DOM, but are instead rendered virtually on top of a single DOM canvas element.
Keeping that in mind, take a look at how jsdom-screenshot renders images (from the explanation of method):
We use jsdom to obtain the state of the HTML which we want to take a screenshot of. Consumers can use jsdom to easily get components into the state they want to take a screenshot of. jsdom-screenshot then uses the markup ("the HTML") at that moment (of that state). jsdom-screenshot launches a local webserver and serves the obtained markup as index.html. It further serves assets provided through serve so that local assets are loaded. Then jsdom-screenshot uses puppeteer to take a screenshot take screenshots of that page using headless Google Chrome.
When you call generateImage(), the HTML you posted (just an empty canvas element) is copied into a file, index.html, opened in Puppeteer, then a screenshot is taken. Because canvas elements don't include their contents in their markup, when the HTML is copied into a file the chart is lost.
In short, jsdom-screenshot does not support drawing on canvas elements.
I would recommend checking out jest-puppeteer, which runs your entire test suite inside of Puppeteer. Instead of using a virtualized DOM implementation jsdom, it will use the actual Chromium DOM implementation, which has the added benefit of functioning closer to runtime usage. You can use page.screenshot() to take a screenshot of the chart exactly as it appears in-browser, with full DOM support (canvas included). Check out the jest-puppeteer README to get started.
Related
How can I read buffer data from the type script?
I want to use the public key to get all the token lists I own.
I'm trying to get this, but an empty array of objects is being returned.
import {Connection, Keypair} from "#solana/web3.js";
const Solana = new Connection("https://api.testnet.solana.com/","confirmed")
const getInfo = async () => {
const recentInfo = await Solana.getEpochInfo()
const DEMO_FROM_SECRET_KEY = new Uint8Array([
223, 119, 171, 5, 237, 138, 42, 140, 176, 163, 74,
107, 25, 143, 90, 97, 250, 158, 203, 102, 238, 19,
77, 228, 211, 238, 147, 149, 40, 50, 211, 155, 51,
207, 14, 53, 86, 230, 164, 27, 14, 202, 78, 181,
185, 250, 16, 52, 134, 242, 96, 16, 12, 67, 2,
178, 106, 241, 156, 212, 11, 150, 114, 72])
const keypair = Keypair.fromSecretKey(DEMO_FROM_SECRET_KEY)
console.log("=============get account info==============")
async function fetchaccountdata() {
const accountinfo = await Solana.getParsedAccountInfo(keypair.publicKey,"max")
const accountinfodata = JSON.stringify(accountinfo)
const accountinfodata2 = JSON.parse(accountinfodata)
console.log(accountinfo)
console.log("=============get account info==============")
console.log(accountinfodata)
console.log(accountinfodata2)
}
fetchaccountdata()
}
getInfo()
Terminal is
accountinfodata = {"context":{"slot":94636033},"value":{"data":{"type":"Buffer","data":[]},"executable":false,"lamports":42784111360,"owner":{"_bn":"00"},"rentEpoch":231}}
accountinfodata2 = {
context: { slot: 94636033 },
value: {
data: { type: 'Buffer', data: [] },
executable: false,
lamports: 42784111360,
owner: { _bn: '00' },
rentEpoch: 231
}
}
The data of accountinfo object is empty array.
How can I read the information?
This call is fetching the account data for your wallet. Your wallet only holds SOL, which is why the data is nothing!
If you want to get all of the token accounts that you own, you'll be better off using getParsedTokenAccountsByOwner: https://github.com/solana-labs/solana/blob/2a42f8a06edd4d33c6cda4d66add0a2582d37011/web3.js/src/connection.ts#L2310
The buffer contains account info data in no particular format. Borsh has recently been established as a standard, though.
Example borsh serialization from SPL:
https://github.com/solana-labs/solana-program-library/blob/master/token/program/src/state.rs#L128
Example borsh deserialization for metaplex metadata: https://github.com/metaplex-foundation/metaplex-program-library/blob/master/token-metadata/program/src/instruction.rs#L77-L78
If you aren't trying to decode metaplex metadata, you should look elsewhere for the schema, but follow the same principles of the code. If you know the account isn't using borsh, then it's up to you to decode it.
Visit the solana tech discord for more information/help.
https://discord.com/channels/428295358100013066/517163444747894795/917412508418068510
function createData(collegeName, registrarName, phoneNumber, emailAddress, action) {
return {collegeName , registrarName, phoneNumber, emailAddress, action };
}
var rows = [
createData("data", 305, 3.7, 67, 4.3),
createData('Donut', 452, 25.0, 51, 4.9),
createData('Eclair', 262, 16.0, 24, 6.0),
createData('Frozen yoghurt', 159, 6.0, 24, 4.0),
createData('Gingerbread', 356, 16.0, 49, 3.9),
createData('Honeycomb', 408, 3.2, 87, 6.5),
createData('Ice cream sandwich', 237, 9.0, 37, 4.3),
createData('Jelly Bean', 375, 0.0, 94, 0.0),
createData('KitKat', 518, 26.0, 65, 7.0),
createData('Lollipop', 392, 0.2, 98, 0.0),
createData('Marshmallow', 318, 0, 81, 2.0),
createData('Nougat', 360, 19.0, 9, 37.0),
createData('Oreo', 437, 18.0, 63, 4.0),
];
this is static data (you can check using full code for table ) but i want to feed rows by dynamic data :this is the response of database
You shoul use a Map to generate an input for your table rows property:
let list = (data && data.profiles != null) ? data.profiles.map((value, index, array) => {
return {
id: value.id,
key: value.id,
name: value.name,
})
Above code is an example, change variables to your owns.
I'm trying to receive SSE data as JSON in my Flutter app. But instead of getting the data I'm getting the following repeated arrays of numbers in my console.
I/flutter (17286): Received streamedResponse.statusCode:200
I/flutter (17286): Received data:[100, 97, 116, 97, 58, 32, 123, 34, 109, 115, 103, 34, 58, 34, 84, 104, 105, 115, 32, 105, 115, 32, 109, 121, 32, 109, 101, 115, 115, 97, 103, 101, 34, 125, 10, 10]
I/flutter (17286): Received data:[100, 97, 116, 97, 58, 32, 123, 34, 109, 115, 103, 34, 58, 34, 84, 104, 105, 115, 32, 105, 115, 32, 109, 121, 32, 109, 101, 115, 115, 97, 103, 101, 34, 125, 10, 10]
Here's what the SSE data looks like on the server
data: {"msg":"This is my message"}
data: {"msg":"This is my message"}
data: {"msg":"This is my message"}
(repeated over and over)
And here's the Flutter code;
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class MyApp extends StatelessWidget {
http.Client _client;
MyApp() : super() {
subscribe();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter SSE',
home: Scaffold(
appBar: AppBar(
title: Text('Receive SSE Events'),
),
body: Center(
child: Text('Ready for events..'),
),
),
);
}
subscribe() async {
print("Subscribing..");
try {
_client = http.Client();
var request = new http.Request("GET", Uri.parse("http://18.224.97.18:8080/connect"));
request.headers["Cache-Control"] = "no-cache";
request.headers["Accept"] = "text/event-stream";
Future<http.StreamedResponse> response = _client.send(request);
response.asStream().listen((streamedResponse) {
print("Received streamedResponse.statusCode:${streamedResponse.statusCode}");
streamedResponse.stream.listen((data) {
print("Received data:$data");
});
});
} catch(e) {
print("Caught $e");
}
}
unsubscribe() {
_client.close();
}
}
I'm not sure why "print("Received data:$data") is giving arrays of numbers instead of the {"msg":"This is my message"} in the SSE stream.
Anyone know why I'm getting these numbers instead of the data?
ByteStream is the data being returned from streamedResponse.stream.listen(). To decode the value, you can use utf8.decode(data) like what has been mentioned in the comments.
use flutter_client_sse
package for the Server-Sent-Event Stream data. It returns parsed model of the event, id and the data.
I am using Fabric JS on my Angular7 project. Could you tell me how I can change the shape of the blue-colored hollow-rectangles on the corner of red-rectangle on the image?
Thanks for your attention on this post.
Blue-colored hollow-rectangles in question is here
Thanks.. Found an answer
object.set({
transparentCorners: false,
cornerColor: 'blue',
cornerStrokeColor: 'red',
borderColor: 'red',
cornerSize: 12,
padding: 10,
cornerStyle: 'circle',
borderDashArray: [3, 3]
});
Source: http://fabricjs.com/fabric-intro-part-4#customization
With the following javascript request:
navigator.credentials.create({
publicKey: {
// random, cryptographically secure, at least 16 bytes
challenge: new Uint8Array(16),
// relying party
rp: {
id: 'localhost',
name: 'My website'
},
user: {
id: new Uint8Array(16),
name: 'Tang',
displayName: 'Tang'
},
pubKeyCredParams: [
{
type: "public-key", alg: -7
}
],
attestation: "direct"
}
})
a FIDO2-compatible Yubikey 5 NFC systematically returns a "fido-u2f" attestation statement:
%{
"attStmt" => %{
"sig" => <<48, 69, 2, 33, 0, 132, 31, 225, 91, 58, 61, 190, 47, 66, 168, 8,
177, 18, 136, 106, 100, 219, 54, 52, 255, 103, 106, 156, 230, 141, 240,
82, 130, 167, 204, 128, 100, 2, 32, 61, 159, 126, 9, 244, 55, 100, 123,
169, ...>>,
"x5c" => [
<<48, 130, 2, 188, 48, 130, 1, 164, 160, 3, 2, 1, 2, 2, 4, 3, 173, 240,
18, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 11, 5, 0, 48, 46, 49,
44, 48, 42, 6, 3, 85, 4, 3, 19, ...>>
]
},
"authData" => <<73, 150, 13, 229, 136, 14, 140, 104, 116, 52, 23, 15, 100,
118, 96, 91, 143, 228, 174, 185, 162, 134, 50, 199, 153, 92, 243, 186, 131,
29, 151, 99, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...>>,
"fmt" => "fido-u2f"
}
How to receive a FIDO2 "packed" attestation statement instead?
Per the current spec/standard I don't think you (acting as a Relying Party) can "select" which attestation statement format you receive from the Authenticator (i.e. "the device"). That is a decision made by the Authenticator.
I think MacBook Pro TouchID platform authenticator via Chrome Desktop is sending "packed" attestation statements, if that helps.
There is no way to select the attestation using such simple keys. To test my implementation for both attestations I simply bought two different keys one from Yibico and one from Nitrokey. Yubico sends fido-u2f, while the Nitrokey sends packed attestations.
And if someone likes to know, this is how I implemented that:
let verifyAuthenticatorAttestationResponse = (webAuthnResponse) => {
let attestationBuffer =
base64url.toBuffer(webAuthnResponse.response.attestationObject);
let ctapMakeCredResp = cbor.decodeAllSync(attestationBuffer)[0];
let authrDataStruct = parseMakeCredAuthData(ctapMakeCredResp.authData);
let response = {'verified': false };
if(ctapMakeCredResp.fmt === 'fido-u2f' || ctapMakeCredResp.fmt === 'packed') {
if(!(authrDataStruct.flags & U2F_USER_PRESENTED))
throw new Error('User was NOT presented durring authentication!');
let clientDataHash =
hash(base64url.toBuffer(webAuthnResponse.response.clientDataJSON))
let publicKey = COSEECDHAtoPKCS(authrDataStruct.COSEPublicKey)
let PEMCertificate = ASN1toPEM(ctapMakeCredResp.attStmt.x5c[0]);
let signature = ctapMakeCredResp.attStmt.sig;
let signatureBase;
if(ctapMakeCredResp.fmt === 'fido-u2f') {
signatureBase = Buffer.concat([Buffer.from([0x00]), authrDataStruct.rpIdHash, clientDataHash, authrDataStruct.credID, publicKey]);
} else {
signatureBase = Buffer.concat([ctapMakeCredResp.authData, clientDataHash]);
}
response.verified = verifySignature(signature, signatureBase, PEMCertificate)
if(response.verified) {
response.authrInfo = {
fmt: `${ctapMakeCredResp.fmt}`,
publicKey: base64url.encode(publicKey),
counter: authrDataStruct.counter,
credID: base64url.encode(authrDataStruct.credID)
}
}
}
return response
}
By default the browser might select U2F. Try forcing UV by setting it to "required". This will force browser to use FIDO2 as U2F does not support UV.