Skip to content

Commit

Permalink
#4495 - Macro: UI support for IDT import/export
Browse files Browse the repository at this point in the history
  • Loading branch information
ilya-asiyuk-epam committed Apr 29, 2024
1 parent 65a15fa commit 091564b
Show file tree
Hide file tree
Showing 23 changed files with 168 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { test, expect } from '@playwright/test';
import {
TopPanelButton,
openFileAndAddToCanvasMacro,
selectTopPanelButton,
takeEditorScreenshot,
waitForPageInit,
saveToFile,
openFile,
receiveFileComparisonData,
selectOptionInDropdown,
pressButton,
chooseFileFormat,
readFileContents,
moveMouseAway,
getIdt,
} from '@utils';
import { turnOnMacromoleculesEditor } from '@utils/macromolecules';

function removeNotComparableData(file: string) {
return file.replaceAll('\r', '');
}
test.describe('Import-Saving .idt Files', () => {
test.beforeEach(async ({ page }) => {
await waitForPageInit(page);
await turnOnMacromoleculesEditor(page);
});

test(`Import .idt file`, async ({ page }) => {
await openFileAndAddToCanvasMacro('IDT/idt-a.idt', page);
await moveMouseAway(page);
await takeEditorScreenshot(page);
});

test('Import incorrect data', async ({ page }) => {
const randomText = '!+%45#asjfnsalkfl';
await selectTopPanelButton(TopPanelButton.Open, page);
await page.getByTestId('paste-from-clipboard-button').click();
await page.getByTestId('open-structure-textarea').fill(randomText);
await chooseFileFormat(page, 'IDT');
await page.getByTestId('add-to-canvas-button').click();
await takeEditorScreenshot(page);
});

test('Check import of .ket file and save in .idt format', async ({
page,
}) => {
await openFileAndAddToCanvasMacro('KET/rna-a.ket', page);
const expectedFile = await getIdt(page);
await saveToFile('IDT/idt-rna-a.idt', expectedFile);

const METADATA_STRING_INDEX = [1];

const { fileExpected: idtFileExpected, file: idtFile } =
await receiveFileComparisonData({
page,
expectedFileName: 'tests/test-data/IDT/idt-rna-a.idt',
metaDataIndexes: METADATA_STRING_INDEX,
});

expect(idtFile).toEqual(idtFileExpected);

await takeEditorScreenshot(page);
});

test('Check that empty file can be saved in .idt format', async ({
page,
}) => {
const expectedFile = await getIdt(page);
await saveToFile('IDT/idt-empty.idt', expectedFile);

const METADATA_STRING_INDEX = [1];

const { fileExpected: idtFileExpected, file: idtFile } =
await receiveFileComparisonData({
page,
expectedFileName: 'tests/test-data/IDT/idt-empty.idt',
metaDataIndexes: METADATA_STRING_INDEX,
});

expect(idtFile).toEqual(idtFileExpected);
});

test('Check that system does not let importing empty .idt file', async ({
page,
}) => {
await selectTopPanelButton(TopPanelButton.Open, page);
await openFile('IDT/idt-empty.idt', page);
await page.getByText('Add to Canvas').isDisabled();
});

test('Check that system does not let uploading corrupted .idt file', async ({
page,
}) => {
await selectTopPanelButton(TopPanelButton.Open, page);

const filename = 'IDT/idt-corrupted.idt';
await openFile(filename, page);
await selectOptionInDropdown(filename, page);
await pressButton(page, 'Add to Canvas');
await takeEditorScreenshot(page);
});

test('Should open .ket file and modify to .idt format in save modal textarea', async ({
page,
}) => {
await openFileAndAddToCanvasMacro('KET/rna-a.ket', page);
await selectTopPanelButton(TopPanelButton.Save, page);
await chooseFileFormat(page, 'IDT');
await page
.getByTestId('dropdown-select')
.getByRole('combobox')
.allInnerTexts();

const textArea = page.getByTestId('preview-area-text');
const file = await readFileContents('tests/test-data/IDT/idt-rna-a.idt');
const expectedData = removeNotComparableData(file);
const valueInTextarea = removeNotComparableData(
await textArea.inputValue(),
);
expect(valueInTextarea).toBe(expectedData);
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions ketcher-autotests/tests/test-data/IDT/idt-a.idt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
A
1 change: 1 addition & 0 deletions ketcher-autotests/tests/test-data/IDT/idt-corrupted.idt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!+-$#12w12r23e32e33
Empty file.
1 change: 1 addition & 0 deletions ketcher-autotests/tests/test-data/IDT/idt-rna-a.idt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rA/3Phos/
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const GetFileMethod: Record<string, keyof Ketcher> = {
sdf: 'getSdf',
fasta: 'getFasta',
seq: 'getSequence',
idt: 'getIdt',
} as const;

type KetcherApiFunction = (format?: string) => Promise<string>;
Expand Down
4 changes: 4 additions & 0 deletions ketcher-autotests/tests/utils/formats/formats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export async function getFasta(page: Page): Promise<string> {
return await page.evaluate(() => window.ketcher.getFasta());
}

export async function getIdt(page: Page): Promise<string> {
return await page.evaluate(() => window.ketcher.getIdt());
}

export async function getSequence(page: Page): Promise<string> {
return await page.evaluate(() => window.ketcher.getSequence());
}
Expand Down
2 changes: 1 addition & 1 deletion ketcher-autotests/tests/utils/macromolecules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export async function scrollDown(page: Page, scrollDelta: number) {

export async function chooseFileFormat(
page: Page,
fileFomat: 'Ket' | 'MDL Molfile V3000' | 'FASTA' | 'Sequence',
fileFomat: 'Ket' | 'MDL Molfile V3000' | 'FASTA' | 'Sequence' | 'IDT',
) {
await page.getByTestId('dropdown-select').click();
await waitForSpinnerFinishedWork(page, async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ export const macromoleculesFilesInputFormats = {
dna: 'chemical/x-dna-fasta',
peptide: 'chemical/x-peptide-fasta',
},
idt: 'chemical/x-idt',
};
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ const formatProperties: FormatPropertiesMap = {
['.fasta'],
true,
),
idt: new SupportedFormatProperties(
'IDT',
ChemicalMimeType.IDT,
['.idt'],
false,
),
sequence: new SupportedFormatProperties(
'SEQUENCE',
ChemicalMimeType.SEQUENCE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export enum SupportedFormat {
sdfV3000 = 'sdfV3000',
fasta = 'fasta',
sequence = 'sequence',
idt = 'idt',
unknown = 'unknown',
}

Expand Down
9 changes: 9 additions & 0 deletions packages/ketcher-core/src/application/ketcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,15 @@ export class Ketcher {
return molfile;
}

getIdt(): Promise<string> {
return getStructure(
SupportedFormat.idt,
this.#formatterFactory,
this.#editor.struct(),
CoreEditor.provideEditorInstance()?.drawingEntitiesManager,
);
}

async getRxn(molfileFormat: MolfileFormat = 'v2000'): Promise<string> {
if (window.isPolymerEditorTurnedOn) {
throw new Error('RXN format is not available in macro mode');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export enum ChemicalMimeType {
RNA = 'chemical/x-rna-sequence',
DNA = 'chemical/x-dna-sequence',
PEPTIDE = 'chemical/x-peptide-sequence',
IDT = 'chemical/x-idt',
}

export interface WithStruct {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ const options: Array<Option> = [
{ id: 'mol', label: 'MDL Molfile V3000' },
{ id: 'seq', label: 'Sequence' },
{ id: 'fasta', label: 'FASTA' },
{ id: 'idt', label: 'IDT' },
];

const additionalOptions: Array<Option> = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@ const options: Array<Option> = [
{ id: 'mol', label: 'MDL Molfile V3000' },
{ id: 'sequence', label: 'Sequence' },
{ id: 'fasta', label: 'FASTA' },
{ id: 'idt', label: 'IDT' },
];

const formatDetector = {
mol: ChemicalMimeType.Mol,
fasta: ChemicalMimeType.FASTA,
sequence: ChemicalMimeType.SEQUENCE,
idt: ChemicalMimeType.IDT,
};

const StyledModal = styled(Modal)({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
SupportedFormatProperties,
} from './supportedFormatProperties';

export type SupportedFormats = 'mol' | 'ket' | 'fasta' | 'sequence';
export type SupportedFormats = 'mol' | 'ket' | 'fasta' | 'sequence' | 'idt';

type FormatProperties = {
[key in SupportedFormats]: SupportedFormatProperties;
Expand Down Expand Up @@ -54,6 +54,13 @@ const formatProperties: FormatProperties = {
false,
{},
),
idt: new SupportedFormatProperties(
'IDT',
ChemicalMimeType.Idt,
['.idt'],
false,
{},
),
};

export const getPropertiesByFormat = (format: SupportedFormats) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export enum ChemicalMimeType {
Helm = 'chemical/x-helm',
Fasta = 'chemical/x-fasta',
Sequence = 'chemical/x-sequence',
Idt = 'chemical/x-idt',
}

interface SupportedFormatPropertiesOptions {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export enum SupportedFormat {
SDF = 'sdf',
FASTA = 'fasta',
SEQUENCE = 'sequence',
IDT = 'idt',
}

export interface WithStruct {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ function convertMimeTypeToOutputFormat(
format = SupportedFormat.SEQUENCE;
break;
}
case ChemicalMimeType.IDT: {
format = SupportedFormat.IDT;
break;
}
case ChemicalMimeType.UNKNOWN:
default: {
throw new Error('Unsupported chemical mime type');
Expand Down Expand Up @@ -271,10 +275,10 @@ class IndigoService implements StructService {
struct,
} = data;
const format = convertMimeTypeToOutputFormat(outputFormat);
console.log('convert format', format);

return new Promise((resolve, reject) => {
const action = ({ data }: OutputMessageWrapper) => {
console.log('convert action', data);
const msg: OutputMessage<string> = data;
if (msg.inputData === struct) {
if (!msg.hasError) {
Expand Down

0 comments on commit 091564b

Please sign in to comment.