Skip to content

Commit

Permalink
fix: upload files with required inputs in native automation (#8092)
Browse files Browse the repository at this point in the history
<!--
Thank you for your contribution.

Before making a PR, please read our contributing guidelines at

https://github.com/DevExpress/testcafe/blob/master/CONTRIBUTING.md#code-contribution

We recommend creating a *draft* PR, so that you can mark it as 'ready
for review' when you are done.
-->

## Purpose
UploadAutomation is fixed in order to upload required inputs in Native
Automation mode.

## Approach
Remove the required attribute from the file input before uploading. 
Initialize the addInternalEventAfterListener on inputs form 'submit'
event for returning the required attributes back.

## References
closes #8079

## Pre-Merge TODO
- [x] Write tests for your proposed changes
- [x] Make sure that existing tests do not fail

---------

Co-authored-by: aleks-pro <alexander.prokhorov@hotmail.com>
  • Loading branch information
Bayheck and aleks-pro committed Nov 29, 2023
1 parent 89c71b6 commit ea902cb
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 13 deletions.
29 changes: 27 additions & 2 deletions src/client/automation/playback/upload.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,37 @@
import { doUpload } from '../deps/hammerhead';
import {
doUpload,
eventSandbox,
nativeMethods,
} from '../deps/hammerhead';
import { arrayUtils } from '../deps/testcafe-core';


const REQUIRED_ATTR_NAME = 'required';
const FORM_SUBMIT_EVENT_NAME = 'submit';

export default class UploadAutomation {
constructor (element, paths, createError) {
constructor (element, paths, createError, isNativeAutomation) {
this.element = element;
this.paths = paths;
this.createError = createError;

if (isNativeAutomation && this.element.form)
this._handleRequiredInput();
}

_handleRequiredInput () {
const isRequired = nativeMethods.hasAttribute.call(this.element, REQUIRED_ATTR_NAME);

if (isRequired)
nativeMethods.removeAttribute.call(this.element, REQUIRED_ATTR_NAME);

const ensureUploadInputHasRequiredAttribute = () => {
if (isRequired)
nativeMethods.setAttribute.call(this.element, REQUIRED_ATTR_NAME, 'true');
};

eventSandbox.listeners.initElementListening(this.element.form, [FORM_SUBMIT_EVENT_NAME]);
eventSandbox.listeners.addInternalEventAfterListener(this.element.form, [FORM_SUBMIT_EVENT_NAME], ensureUploadInputHasRequiredAttribute);
}

run () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,10 @@ function ensureFileInput (element: Node[]): never | void {
}

ActionExecutor.ACTIONS_HANDLERS[COMMAND_TYPE.setFilesToUpload] = {
create: (command, elements) => {
create: (command, elements, dispatchNativeAutomationEventFn) => {
return new UploadAutomation(elements[0], command.filePath,
(filePaths: string[], scannedFilePaths: string[]) => new ActionCannotFindFileToUploadError(filePaths, scannedFilePaths),
dispatchNativeAutomationEventFn
);
},

Expand Down
24 changes: 14 additions & 10 deletions test/functional/fixtures/api/es-next/upload/pages/index.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Upload</title>
</head>
<body>
<form action="/file-upload" method="POST" enctype="multipart/form-data">
<input type="file" id="file" name="file">
<input type="submit" id="submit">
</form>
</body>
<head>
<meta charset="UTF-8" />
<title>Upload</title>
</head>
<body>
<form action="/file-upload" method="POST" enctype="multipart/form-data">
<input type="file" id="file" name="file" />
<input type="submit" id="submit" />
</form>
<form action="/file-upload" method="POST" enctype="multipart/form-data">
<input type="file" id="fileRequired" name="fileRequired" required />
<input type="submit" id="submitRequired" />
</form>
</body>
</html>
4 changes: 4 additions & 0 deletions test/functional/fixtures/api/es-next/upload/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ describe('[API] Upload', function () {
return runTests('./testcafe-fixtures/upload-test.js', 'Upload the file', { only: 'chrome' });
});

it('Should upload the specified file with required input', function () {
return runTests('./testcafe-fixtures/upload-test.js', 'Upload the file with required input', { only: 'chrome' });
});

it('Should validate the selector argument', function () {
return runTests('./testcafe-fixtures/upload-test.js', 'Invalid selector argument (setFilesToUpload)', {
shouldFail: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,11 @@ test('Invalid selector argument (clearUpload)', async t => {
test('Error on upload non-existing file', async t => {
await t.setFilesToUpload('#file', ['../dummy-file-1.txt', '../dummy-file-2.txt']);
});

test('Upload the file with required input', async t => {
await t
.setFilesToUpload('#fileRequired', '../test-data/file1.txt')
.click('#submitRequired');

expect(await getUploadedText()).equals('File 1 is uploaded!');
});

0 comments on commit ea902cb

Please sign in to comment.