@Test
	public void testCopyTextSelection_ByteViewer_SingleLayout() throws Exception {

		ByteViewerOptionsDialog dialog = launchByteViewerOptions();
		setByteViewerViewSelected(dialog, "Ascii", true);
		setByteViewerViewSelected(dialog, "Octal", true);
		pressButtonByText(dialog.getComponent(), "OK");

		ByteViewerPlugin plugin = env.getPlugin(ByteViewerPlugin.class);
		ProgramByteViewerComponentProvider provider = plugin.getProvider();
		ByteViewerPanel panel =
			(ByteViewerPanel) invokeInstanceMethod("getByteViewerPanel", provider);

		Window window = windowForComponent(panel);
		assertNotNull(window);
		Dimension size = window.getSize();
		window.setSize(1000, size.height);// resize so that we can click the various views

		//
		// Test copying from the Hex view
		//
		ByteViewerComponent bc = findByteViewerComponent(panel, "Hex");
		assertTrue(bc.isVisible());

		Rectangle bounds = bc.getBounds();
		clickMouse(bc, 1, bounds.x + 20, bounds.y + 20, 1, 0);

		ProgramSelection selection = new ProgramSelection(addr("1001050"), addr("1001052"));
		tool.firePluginEvent(new ProgramSelectionPluginEvent("Test", selection, program));

		waitForBusyTool(tool);

		final DockingAction byteViewerCopyAction =
			getAction(byteViewerClipboardProvider, COPY_ACTION_NAME);
		runSwing(() -> byteViewerCopyAction.actionPerformed(getActionContext(byteViewerWrapper)));

		Clipboard systemClipboard = GClipboard.getSystemClipboard();
		Transferable contents = systemClipboard.getContents(systemClipboard);
		assertNotNull(contents);
		assertTrue("Contents not copied into system clipboard", (contents != DUMMY_TRANSFERABLE));
		Object data = contents.getTransferData(DataFlavor.stringFlavor);
		assertEquals("0e 5e f4", data);

		//
		// Test copying from the Hex view
		//
		bc = findByteViewerComponent(panel, "Ascii");
		assertTrue(bc.isVisible());

		bounds = bc.getBounds();
		clickMouse(bc, 1, bounds.x + 20, bounds.y + 20, 1, 0);

		selection = new ProgramSelection(addr("1001050"), addr("1001052"));
		tool.firePluginEvent(new ProgramSelectionPluginEvent("Test", selection, program));

		waitForBusyTool(tool);

		runSwing(() -> byteViewerCopyAction.actionPerformed(getActionContext(byteViewerWrapper)));

		systemClipboard = GClipboard.getSystemClipboard();
		contents = systemClipboard.getContents(systemClipboard);
		assertNotNull(contents);
		assertTrue("Contents not copied into system clipboard", (contents != DUMMY_TRANSFERABLE));
		data = contents.getTransferData(DataFlavor.stringFlavor);
		assertEquals(". ^ .", data);

		//
		// Test copying from the Octal view
		//
		bc = findByteViewerComponent(panel, "Octal");
		assertTrue(bc.isVisible());

		bounds = bc.getBounds();
		clickMouse(bc, 1, bounds.x + 20, bounds.y + 20, 1, 0);

		selection = new ProgramSelection(addr("1001050"), addr("1001052"));
		tool.firePluginEvent(new ProgramSelectionPluginEvent("Test", selection, program));

		waitForBusyTool(tool);

		runSwing(() -> byteViewerCopyAction.actionPerformed(getActionContext(byteViewerWrapper)));

		systemClipboard = GClipboard.getSystemClipboard();
		contents = systemClipboard.getContents(systemClipboard);
		assertNotNull(contents);
		assertTrue("Contents not copied into system clipboard", (contents != DUMMY_TRANSFERABLE));
		data = contents.getTransferData(DataFlavor.stringFlavor);
		assertEquals("016 136 364", data);
	}
Note: This test is sensitive to focus. So, don't click any windows while this test is running.
Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/app/plugin/core/clipboard/ClipboardPluginTest.java