Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#4495 - Macro: UI support for IDT import/export #4549

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading