AWS StepFunction CDK resultpath set to null - aws-cdk

I am not able to find a way to specify 'null' to result path.
As pointed out here:
https://docs.aws.amazon.com/step-functions/latest/dg/input-output-resultpath.html
I want to implement, in CDK, this: "Discard the Result and Keep the Original Input"
I have read this discussion:
https://github.com/aws/aws-cdk/issues/1805
but there is no final answer although it has been closed.
Below a code snip:
const verifyDeviceJob = new tasks.LambdaInvoke(this, 'VerifyDeviceJobTask', {
lambdaFunction: verifyConditionDeviceFn,
inputPath: '$.detail',
resultPath: //HOW TO DECLARE IT TO NULL??
});

You use special value DISCARD https://docs.aws.amazon.com/cdk/api/latest/docs/#aws-cdk_aws-stepfunctions.JsonPath.html#static-discard
So the snip would be like
const verifyDeviceJob = new tasks.LambdaInvoke(this, 'VerifyDeviceJobTask', {
lambdaFunction: verifyConditionDeviceFn,
inputPath: '$.detail',
resultPath: JsonPath.DISCARD
});

Related

playwirght - drag and drop files

I'm looking at automating a drag and drop scenario using Playwright. I found this code which is meant to do just this:
// Read your file into a buffer.
const buffer = readFileSync('./runtime_config/common/file.pdf');
// Create the DataTransfer and File
const dataTransfer = await scope.page.evaluateHandle((data) => {
const dt = new DataTransfer();
// Convert the buffer to a hex array
const file = new File([data.toString('hex')], 'file.pdf', { type: 'application/pdf' });
dt.items.add(file);
return dt;
}, buffer);
// Now dispatch
await page.dispatchEvent('YOUR_TARGET_SELECTOR', 'drop', { dataTransfer });
This code was found on this github post https://github.com/microsoft/playwright/issues/10667
When I try to use this code, I get an error that 'scope is not defined'
I can't see how this would work, nor does the post have any info. I've reached out to the poster but no reply yet, so thought I'd try here. Anyone know how this would work?
(I tried modify the line to be this.page.evaluateHandle((data) which doesn't error at runtime, but all I am getting is a 15B file called 'file.pdf' in the UI. I have console.log the buffer and it does appear to be valid.)

aws cdk lambda, appconfig typescript example please?

Can anyone provide or point at an AWS-CDK/typescript example provisioning an AWS AppConfig app/env/config consumed by a lambda please? Could not find anything meaningful online.
A little late to this party, If anyone is coming to this question, looking for a quick answer, here you go:
AppConfig Does Not Have Any Official L2 Constructs
This means that one has to work with L1 constructs currently vended here
This is ripe for someone authoring an L2/L3 construct (I am working on vending this custom construct soon - so keep an eye out on updates here).
This does not mean its hard to use AppConfig in CDK, its just that unlike L2/L3 constructs, we have to dig deeper into setting AppConfig up reading their documentation.
A Very Simple Example (YMMV)
Here is a custom construct I have to setup AppConfig:
import {
CfnApplication,
CfnConfigurationProfile,
CfnDeployment,
CfnDeploymentStrategy,
CfnEnvironment,
CfnHostedConfigurationVersion,
} from "aws-cdk-lib/aws-appconfig";
import { Construct } from "constructs";
// 1. https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appconfig-readme.html - there are no L2 constructs for AppConfig.
// 2. https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-working.html- this the CDK code from this console setup guide.
export class AppConfig extends Construct {
constructor(scope: Construct, id: string) {
super(scope, id);
// create a new app config application.
const testAppConfigApp: CfnApplication = new CfnApplication(
this,
"TestAppConfigApp",
{
name: "TestAppConfigApp",
}
);
// you can customize this as per your needs.
const immediateDeploymentStrategy = new CfnDeploymentStrategy(
this,
"DeployStrategy",
{
name: "ImmediateDeployment",
deploymentDurationInMinutes: 0,
growthFactor: 100,
replicateTo: "NONE",
finalBakeTimeInMinutes: 0,
}
);
// setup an app config env
const appConfigEnv: CfnEnvironment = new CfnEnvironment(
this,
"AppConfigEnv",
{
applicationId: testAppConfigApp.ref,
// can be anything that makes sense for your use case.
name: "Production",
}
);
// setup config profile
const appConfigProfile: CfnConfigurationProfile = new CfnConfigurationProfile(
this,
"ConfigurationProfile",
{
name: "TestAppConfigProfile",
applicationId: testAppConfigApp.ref,
// we want AppConfig to manage the configuration profile, unless we need from SSM or S3.
locationUri: "hosted",
// This can also be "AWS.AppConfig.FeatureFlags"
type: "AWS.Freeform",
}
);
// Update AppConfig
const configVersion: CfnHostedConfigurationVersion = new CfnHostedConfigurationVersion(
this,
"HostedConfigurationVersion",
{
applicationId: testAppConfigApp.ref,
configurationProfileId: appConfigProfile.ref,
content: JSON.stringify({
someAppConfigResource: "SomeAppConfigResourceValue",
//... add more as needed.
}),
// https://www.rfc-editor.org/rfc/rfc9110.html#name-content-type
contentType: "application/json",
}
);
// Perform deployment.
new CfnDeployment(this, "Deployment", {
applicationId: testAppConfigApp.ref,
configurationProfileId: appConfigProfile.ref,
configurationVersion: configVersion.ref,
deploymentStrategyId: immediateDeploymentStrategy.ref,
environmentId: appConfigEnv.ref,
});
}
}
Here is what goes inside my lambda handler (please note that you should have lambda layers enabled for AppConfig extension, see more information here):
const http = require('http');
exports.handler = async (event) => {
const res = await new Promise((resolve, reject) => {
http.get(
"http://localhost:2772/applications/TestAppConfigApp/environments/Production/configurations/TestAppConfigProfile",
resolve
);
});
let configData = await new Promise((resolve, reject) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('error', err => reject(err));
res.on('end', () => resolve(data));
});
const parsedConfigData = JSON.parse(configData);
return parsedConfigData;
};
EDIT: As promised, I released a new npm library : https://www.npmjs.com/package/cdk-appconfig, as of this update, this is still pre-release, but time permitting I will release a 1.x soon. But this will allow people to check out/fork if need be. Please share feedback/or open PRs if you'd like to collaborate.
I have no experience with AWS AppConfig. But I would start here and here

cy.url() and/or cy.location('href') does not return a string

I have an editor page. When I add any content and click the "Save" button my URL will change, adding a random id in the URL. I want to check if my ID's are changing every time when I click the "Save button".
I save the URL result in variable and want to check it, I do it like this:
const currentURL = cy.url();
cy.get('.editor-toolbar-actions-save').click();
cy.url().should('not.eq', currentURL);
But my currentURL variable's type is not string:
expected http://localhost:8080/editor/37b44d4d-48b7-4d19-b3de-56b38fc9f951 to not equal { Object (chainerId, firstCall) }
How I can use my variable?
tl;dr
Cypress commands are asynchronous, you have to use then to work with their yields.
cy.url().then(url => {
cy.get('.editor-toolbar-actions-save').click();
cy.url().should('not.eq', url);
});
Explanation
A similar question was asked on GitHub, and the official document on aliases explains this phenomenon in great detail:
You cannot assign or work with the return values of any Cypress command. Commands are enqueued and run asynchronously.
The solution is shown too:
To access what each Cypress command yields you use .then().
cy.get('button').then(($btn) => {
// $btn is the object that the previous
// command yielded us
})
It is also a good idea to check out the core concepts docs's section on asynchronicity.
These commands return a chainable type, not primitive values like strings, so assigning them to variables will require further action to 'extract' the string.
In order to get the url string, you need to do
cy.url().then(urlString => //do whatever)
I have been having the same issue and so far most consistent method has been to save the URL to file and read it from file when you need to access it again:
//store the url into a file so that we can read it again elsewhere
cy.url().then(url => {
const saveLocation = `cypress/results/data/${Cypress.spec.name}.location.txt`
cy.writeFile(saveLocation, getUrl)
})
//elsewhere read the file and do thing with it
cy.readFile(`cypress/results/data/${Cypress.spec.name}.location.txt`).then((url) => {
cy.log(`returning back to editor ${url}`)
cy.visit(url)
})
Try this:
describe("Test Suite", () => {
let savedUrl;
beforeEach(() => {
cy.visit("https://duckduckgo.com/");
cy.url().then(($url) => {
savedUrl = $url;
});
});
it("Assert that theURL after the search doens't equal the URL before.", () => {
cy.get("#search_form_input_homepage").type("duck");
cy.get("#search_button_homepage").click();
// Check if this URL "https://duckduckgo.com/?q=duck&t=h_&ia=web"
// doesn't equal the saved URL "https://duckduckgo.com/"
cy.url().should("not.eq", savedUrl);
});
});
Refer below code snippet, Here you can get the current URL and store it in a variable, do print via cy.log()
context('Get Current URL', () => {
it('Get current url and print', () => {
cy.visit('https://docs.cypress.io/api/commands/url')
cy.url().then(url => {
const getUrl = url
cy.log('Current URL is : '+getUrl)
})
})
})
#Max thanks this helped to get some ideas on different versions.
The way I did it is:
Create a .json file in your fixtures folder (name it whatever you want).
On the new .json file, only add: { } brackets and leave the rest blank. The function will self populate that .json file.
Create a new function on the commands page to easily call it on your test.
It would probably be best to create two functions, 1 function to write url or the sliced piece of the url, and the another function to call it so you can use it.
A. Example of 1st method, this method cuts the id off of the URL and stores it on the .json file:
Cypress.Commands.add('writeToJSON', (nameOfJSONSlicedSection) =>
{
cy.url().then(urlID =>
{
let urlBit = urlID.slice(urlID.indexOf('s/') + 2, urlID.indexOf('/edit'))
cy.writeFile('cypress/fixtures/XYZ.json', {name: nameOfJSONSlicedSection, id: urlBit}) /*{ }<-- these will populate the json file with name: xxxxx and id:xxxxx, you can changes those to whatever meets your requirements. using .slice() to take a section of the url. I needed the id that is on the url, so I cut only that section out and put it on the json file.*/
})
})
B. 2nd example function of calling it to be used.
This function is to type in the id that is on the url into a search box, to find the item I require on a different it() block.
Cypress.Commands.add('readJSONFile', (storedJSONFile) =>
{
cy.readFile('cypress/fixtures/XYZ.json').its('id').then((urlSetter) => {
cy.log(storedJSONFile, 'returning ID: ' + urlSetter)
//Search for Story
cy.get('Search text box').should('be.visible').type(urlSetter, {delay: 75})
})
})
/*here I use a .then() and hold the "id" with "urlSetter", then I type it in the search box to find it by the id that is in the URL. Also note that using ".its()" you can call any part section you require, example: .its('name') or .its('id') */
I hope this helps!

How to pipe YAML into EJS in a Gulp stream?

I'm using gulp.js. I want to pipe the resulting JSON data from gulp-yaml, straight into gulp-ejs. My logic says that I'm probably going to have to get synchronous at some point?
What I have tried thus far:
var yaml = require('gulp-yaml');
var ejs = require('gulp-ejs');
gulp.task('yaml', function(){
return gulp.src('./path/to/template.ejs')
.pipe( ejs( gulp.src('./path/to/data.yml').pipe( yaml() ) ) )
.pipe(gulp.dest('./path/to/dest'));
});
I realise that the above is an idiotic script as I'm essentially trying to pass a stream as an argument to ejs. And as predicted, it doesn't work. I've tried numerous other things but I'm guessing someone has done this before?
I reckon gulp-data will have something to do with the solution...
You probably don't need the gulp-data plugin to achieve this; like you said you're just passing the option synchronously to the ejs plugin, and you're only needing the one yaml config file. So this is probably better:
var yaml = require('js-yaml');
var ejs = require('gulp-ejs');
var fs = require('fs');
gulp.task('ejs-with-yaml', function () {
return gulp.src('path/to/template.ejs')
.pipe(ejs(yaml.safeLoad(fs.readFileSync('path/to/data.yml', 'utf-8'))))
.pipe(gulp.dest('path/to/dest'));
});
Okay, so after a bit of head-scratching I've been able to find a solution using js-yaml and gulp-data.
var yaml = require('js-yaml');
var ejs = require('gulp-ejs');
var data = require('gulp-data');
gulp.task('ejs-with-yaml', function(){
return gulp.src('path/to/data.yml'))
.pipe(data(function(file, cb){
// throughput the stream in case of bad/absent file data
if (file.isNull()) return cb( null, file );
if (file.isStream()) return cb( new Error("Streaming not supported") );
// try and convert yaml to json
try {
json = yaml.load(String(file.contents.toString('utf8')));
} catch(e) {
console.log(e);
}
gulp.src('path/to/template.ejs').pipe(ejs(json)).pipe(gulp.dest( 'path/to/dest' ));
}));
});
Hopefully this might help others that are stuck on this. If anyone has a better solution, feel free to comment.

jquery file upload - how to overwrite file NOT rename

I am struggling to update the Jquery file upload plugin so when you upload a file it just overwrites an existing file with the same name instead of renaming it with an upcount.
I have applied the change covered in this link: https://github.com/blueimp/jQuery-File-Upload/issues/1965
but I can't seem overwrite this plugin to get this working?
there's an existing open question not yet answered here: jQuery File Upload by bluimp, how to replace instead of renaming
any guidance on this would be much appreciated.
If you using UploadHandler.php that is exists in the wiki it's simple. In the get_file_name method you should replace this line:
return $this -> get_unique_filename($this -> trim_file_name($name, $type, $index, $content_range), $type, $index, $content_range);
with this:
return $this -> trim_file_name($name, $type, $index, $content_range);
2016 UPDATE to MKoosej's fix!
In UploadHandler.php → protected function get_file_name ...
replace
return $this->get_unique_filename(
$file_path,
$this->fix_file_extension($file_path, $name, $size, $type, $error,
$index, $content_range),
$size,
$type,
$error,
$index,
$content_range
);
with
return $this -> trim_file_name($file_path, $name, $size, $type, $error, $index, $content_range);
I needed the same file overwrite option.
Using the PHP UploadHandler.php file I did a really quick hack which works for me.
I'm sure there is a better way, but this may help others.
Look for handler 'upcount_name_callback' and replace the return statement with the (index) numbering taken out. I left the original return statement in case I need to go back :)
protected function upcount_name_callback($matches) {
$index = isset($matches[1]) ? intval($matches[1]) + 1 : 1;
$ext = isset($matches[2]) ? $matches[2] : '';
return ''.$ext;
/* return ' ('.$index.')'.$ext; */
}
Anno 2018 this could work as well (PHP 7.1):
class MyUploadHandler extends UploadHandler
{
public function __construct($options = array(), $initialize = true, $error_messages = null) {
$options += array(
'overwrite_existing' => true
);
parent::__construct($options, $initialize, $error_messages);
}
protected function get_unique_filename($file_path, $name, $size, $type, $error, $index, $content_range) {
if ($this->options['overwrite_existing'] ?? false) {
return $name;
}
return parent::get_unique_filename($file_path, $name, $size, $type, $error, $index, $content_range);
}
}
It avoids having to change the original code, which then can be used as a library.
Consider the documentation on github (here) and scroll down to where it says "How to tie a file to an element node during the life cycle of an upload". This is the code:
$(function () {
$('#fileupload').fileupload({
dataType: 'json',
add: function (e, data) {
data.context = $('<p/>').text('Uploading...').appendTo(document.body);
data.submit();
},
done: function (e, data) {
data.context.text('Upload finished.');
}
});
});
Pay attention to the done callback function. If you expand the data object you will note there is a data.files object as well as a data.result object. data.result contains the name of the file on the server. Hence, the name of newly uploaded file on the server is data.result.files[0].name based on the example script given above.
I hope this helps someone
I tried solution of #MKoosej. In my case it worked fine, but I've also edited trim_file_name where I make it to return only one filename (I had to do an uploader which transform any filename to data.csv). Also I had to make other version of uploader where I should rewrite filename instead of rename but the different files with different names should remain different. So when I tried there #MKoosej solution it started to upload file with only extension like .jpeg without filename.
So, I found this solution:
in func get_unique_filename in the very beginning I put this:
$oldName=$name;
and returned $oldName instead of $name and it was fine.
Just do a ajax request within the callback for starting upload and erase the file from the data disk. You can find the filename withing data.files[0].name.
Then you just search for the tr with the old link, like this:
$("a[title='"+ data.files[0].name + "']").each(function () {
$(this).closest('tr').fadeOut();
});
and fade it out.
Regards

Resources