Best JavaScript code snippet using storybook-root
storeStressTestConcurrent-test.js
Source:storeStressTestConcurrent-test.js
1/**2 * Copyright (c) Facebook, Inc. and its affiliates.3 *4 * This source code is licensed under the MIT license found in the5 * LICENSE file in the root directory of this source tree.6 *7 * @flow8 */9describe('StoreStressConcurrent', () => {10 let React;11 let ReactDOM;12 let act;13 let actAsync;14 let bridge;15 let store;16 let print;17 beforeEach(() => {18 bridge = global.bridge;19 store = global.store;20 store.collapseNodesByDefault = false;21 React = require('react');22 ReactDOM = require('react-dom');23 act = require('./utils').act;24 // TODO: Figure out recommendation for concurrent mode tests, then replace25 // this helper with the real thing.26 actAsync = require('./utils').actAsync;27 print = require('./storeSerializer').print;28 });29 // TODO: Remove this in favor of @gate pragma30 if (!__EXPERIMENTAL__) {31 it("empty test so Jest doesn't complain", () => {});32 return;33 }34 // This is a stress test for the tree mount/update/unmount traversal.35 // It renders different trees that should produce the same output.36 it('should handle a stress test with different tree operations (Concurrent Mode)', () => {37 let setShowX;38 const A = () => 'a';39 const B = () => 'b';40 const C = () => {41 // We'll be manually flipping this component back and forth in the test.42 // We only do this for a single node in order to verify that DevTools43 // can handle a subtree switching alternates while other subtrees are memoized.44 const [showX, _setShowX] = React.useState(false);45 setShowX = _setShowX;46 return showX ? <X /> : 'c';47 };48 const D = () => 'd';49 const E = () => 'e';50 const X = () => 'x';51 const a = <A key="a" />;52 const b = <B key="b" />;53 const c = <C key="c" />;54 const d = <D key="d" />;55 const e = <E key="e" />;56 function Parent({children}) {57 return children;58 }59 // 1. Render a normal version of [a, b, c, d, e].60 let container = document.createElement('div');61 // $FlowFixMe62 let root = ReactDOM.createRoot(container);63 act(() => root.render(<Parent>{[a, b, c, d, e]}</Parent>));64 expect(store).toMatchInlineSnapshot(65 `66 [root]67 â¾ <Parent>68 <A key="a">69 <B key="b">70 <C key="c">71 <D key="d">72 <E key="e">73 `,74 );75 expect(container.textContent).toMatch('abcde');76 const snapshotForABCDE = print(store);77 // 2. Render a version where <C /> renders an <X /> child instead of 'c'.78 // This is how we'll test an update to a single component.79 act(() => {80 setShowX(true);81 });82 expect(store).toMatchInlineSnapshot(83 `84 [root]85 â¾ <Parent>86 <A key="a">87 <B key="b">88 â¾ <C key="c">89 <X>90 <D key="d">91 <E key="e">92 `,93 );94 expect(container.textContent).toMatch('abxde');95 const snapshotForABXDE = print(store);96 // 3. Verify flipping it back produces the original result.97 act(() => {98 setShowX(false);99 });100 expect(container.textContent).toMatch('abcde');101 expect(print(store)).toBe(snapshotForABCDE);102 // 4. Clean up.103 act(() => root.unmount());104 expect(print(store)).toBe('');105 // Now comes the interesting part.106 // All of these cases are equivalent to [a, b, c, d, e] in output.107 // We'll verify that DevTools produces the same snapshots for them.108 // These cases are picked so that rendering them sequentially in the same109 // container results in a combination of mounts, updates, unmounts, and reorders.110 // prettier-ignore111 const cases = [112 [a, b, c, d, e],113 [[a], b, c, d, e],114 [[a, b], c, d, e],115 [[a, b], c, [d, e]],116 [[a, b], c, [d, '', e]],117 [[a], b, c, d, [e]],118 [a, b, [[c]], d, e],119 [[a, ''], [b], [c], [d], [e]],120 [a, b, [c, [d, ['', e]]]],121 [a, b, c, d, e],122 [<div key="0">{a}</div>, b, c, d, e],123 [<div key="0">{a}{b}</div>, c, d, e],124 [<div key="0">{a}{b}</div>, c, <div key="1">{d}{e}</div>],125 [<div key="1">{a}{b}</div>, c, <div key="0">{d}{e}</div>],126 [<div key="0">{a}{b}</div>, c, <div key="1">{d}{e}</div>],127 [<div key="2">{a}{b}</div>, c, <div key="3">{d}{e}</div>],128 [<span key="0">{a}</span>, b, c, d, [e]],129 [a, b, <span key="0"><span>{c}</span></span>, d, e],130 [<div key="0">{a}</div>, [b], <span key="1">{c}</span>, [d], <div key="2">{e}</div>],131 [a, b, [c, <div key="0">{d}<span>{e}</span></div>], ''],132 [a, [[]], b, c, [d, [[]], e]],133 [[[a, b, c, d], e]],134 [a, b, c, d, e],135 ];136 // 5. Test fresh mount for each case.137 for (let i = 0; i < cases.length; i++) {138 // Ensure fresh mount.139 container = document.createElement('div');140 // $FlowFixMe141 root = ReactDOM.createRoot(container);142 // Verify mounting 'abcde'.143 act(() => root.render(<Parent>{cases[i]}</Parent>));144 expect(container.textContent).toMatch('abcde');145 expect(print(store)).toEqual(snapshotForABCDE);146 // Verify switching to 'abxde'.147 act(() => {148 setShowX(true);149 });150 expect(container.textContent).toMatch('abxde');151 expect(print(store)).toBe(snapshotForABXDE);152 // Verify switching back to 'abcde'.153 act(() => {154 setShowX(false);155 });156 expect(container.textContent).toMatch('abcde');157 expect(print(store)).toBe(snapshotForABCDE);158 // Clean up.159 act(() => root.unmount());160 expect(print(store)).toBe('');161 }162 // 6. Verify *updates* by reusing the container between iterations.163 // There'll be no unmounting until the very end.164 container = document.createElement('div');165 // $FlowFixMe166 root = ReactDOM.createRoot(container);167 for (let i = 0; i < cases.length; i++) {168 // Verify mounting 'abcde'.169 act(() => root.render(<Parent>{cases[i]}</Parent>));170 expect(container.textContent).toMatch('abcde');171 expect(print(store)).toEqual(snapshotForABCDE);172 // Verify switching to 'abxde'.173 act(() => {174 setShowX(true);175 });176 expect(container.textContent).toMatch('abxde');177 expect(print(store)).toBe(snapshotForABXDE);178 // Verify switching back to 'abcde'.179 act(() => {180 setShowX(false);181 });182 expect(container.textContent).toMatch('abcde');183 expect(print(store)).toBe(snapshotForABCDE);184 // Don't unmount. Reuse the container between iterations.185 }186 act(() => root.unmount());187 expect(print(store)).toBe('');188 });189 it('should handle stress test with reordering (Concurrent Mode)', () => {190 const A = () => 'a';191 const B = () => 'b';192 const C = () => 'c';193 const D = () => 'd';194 const E = () => 'e';195 const a = <A key="a" />;196 const b = <B key="b" />;197 const c = <C key="c" />;198 const d = <D key="d" />;199 const e = <E key="e" />;200 // prettier-ignore201 const steps = [202 a,203 b,204 c,205 d,206 e,207 [a],208 [b],209 [c],210 [d],211 [e],212 [a, b],213 [b, a],214 [b, c],215 [c, b],216 [a, c],217 [c, a],218 ];219 const Root = ({children}) => {220 return children;221 };222 // 1. Capture the expected render result.223 const snapshots = [];224 let container = document.createElement('div');225 // $FlowFixMe226 let root = ReactDOM.createRoot(container);227 for (let i = 0; i < steps.length; i++) {228 act(() => root.render(<Root>{steps[i]}</Root>));229 // We snapshot each step once so it doesn't regress.230 snapshots.push(print(store));231 act(() => root.unmount());232 expect(print(store)).toBe('');233 }234 expect(snapshots).toMatchInlineSnapshot(`235 Array [236 "[root]237 â¾ <Root>238 <A key=\\"a\\">",239 "[root]240 â¾ <Root>241 <B key=\\"b\\">",242 "[root]243 â¾ <Root>244 <C key=\\"c\\">",245 "[root]246 â¾ <Root>247 <D key=\\"d\\">",248 "[root]249 â¾ <Root>250 <E key=\\"e\\">",251 "[root]252 â¾ <Root>253 <A key=\\"a\\">",254 "[root]255 â¾ <Root>256 <B key=\\"b\\">",257 "[root]258 â¾ <Root>259 <C key=\\"c\\">",260 "[root]261 â¾ <Root>262 <D key=\\"d\\">",263 "[root]264 â¾ <Root>265 <E key=\\"e\\">",266 "[root]267 â¾ <Root>268 <A key=\\"a\\">269 <B key=\\"b\\">",270 "[root]271 â¾ <Root>272 <B key=\\"b\\">273 <A key=\\"a\\">",274 "[root]275 â¾ <Root>276 <B key=\\"b\\">277 <C key=\\"c\\">",278 "[root]279 â¾ <Root>280 <C key=\\"c\\">281 <B key=\\"b\\">",282 "[root]283 â¾ <Root>284 <A key=\\"a\\">285 <C key=\\"c\\">",286 "[root]287 â¾ <Root>288 <C key=\\"c\\">289 <A key=\\"a\\">",290 ]291 `);292 // 2. Verify that we can update from every step to every other step and back.293 for (let i = 0; i < steps.length; i++) {294 for (let j = 0; j < steps.length; j++) {295 container = document.createElement('div');296 // $FlowFixMe297 root = ReactDOM.createRoot(container);298 act(() => root.render(<Root>{steps[i]}</Root>));299 expect(print(store)).toMatch(snapshots[i]);300 act(() => root.render(<Root>{steps[j]}</Root>));301 expect(print(store)).toMatch(snapshots[j]);302 act(() => root.render(<Root>{steps[i]}</Root>));303 expect(print(store)).toMatch(snapshots[i]);304 act(() => root.unmount());305 expect(print(store)).toBe('');306 }307 }308 // 3. Same test as above, but this time we wrap children in a host component.309 for (let i = 0; i < steps.length; i++) {310 for (let j = 0; j < steps.length; j++) {311 container = document.createElement('div');312 // $FlowFixMe313 root = ReactDOM.createRoot(container);314 act(() =>315 root.render(316 <Root>317 <div>{steps[i]}</div>318 </Root>,319 ),320 );321 expect(print(store)).toMatch(snapshots[i]);322 act(() =>323 root.render(324 <Root>325 <div>{steps[j]}</div>326 </Root>,327 ),328 );329 expect(print(store)).toMatch(snapshots[j]);330 act(() =>331 root.render(332 <Root>333 <div>{steps[i]}</div>334 </Root>,335 ),336 );337 expect(print(store)).toMatch(snapshots[i]);338 act(() => root.unmount());339 expect(print(store)).toBe('');340 }341 }342 });343 it('should handle a stress test for Suspense (Concurrent Mode)', async () => {344 const A = () => 'a';345 const B = () => 'b';346 const C = () => 'c';347 const X = () => 'x';348 const Y = () => 'y';349 const Z = () => 'z';350 const a = <A key="a" />;351 const b = <B key="b" />;352 const c = <C key="c" />;353 const z = <Z key="z" />;354 // prettier-ignore355 const steps = [356 a,357 [a],358 [a, b, c],359 [c, b, a],360 [c, null, a],361 <React.Fragment>{c}{a}</React.Fragment>,362 <div>{c}{a}</div>,363 <div><span>{a}</span>{b}</div>,364 [[a]],365 null,366 b,367 a,368 ];369 const Never = () => {370 throw new Promise(() => {});371 };372 const Root = ({children}) => {373 return children;374 };375 // 1. For each step, check Suspense can render them as initial primary content.376 // This is the only step where we use Jest snapshots.377 const snapshots = [];378 let container = document.createElement('div');379 // $FlowFixMe380 let root = ReactDOM.createRoot(container);381 for (let i = 0; i < steps.length; i++) {382 act(() =>383 root.render(384 <Root>385 <X />386 <React.Suspense fallback={z}>{steps[i]}</React.Suspense>387 <Y />388 </Root>,389 ),390 );391 // We snapshot each step once so it doesn't regress.d392 snapshots.push(print(store));393 act(() => root.unmount());394 expect(print(store)).toBe('');395 }396 expect(snapshots).toMatchInlineSnapshot(`397 Array [398 "[root]399 â¾ <Root>400 <X>401 â¾ <Suspense>402 <A key=\\"a\\">403 <Y>",404 "[root]405 â¾ <Root>406 <X>407 â¾ <Suspense>408 <A key=\\"a\\">409 <Y>",410 "[root]411 â¾ <Root>412 <X>413 â¾ <Suspense>414 <A key=\\"a\\">415 <B key=\\"b\\">416 <C key=\\"c\\">417 <Y>",418 "[root]419 â¾ <Root>420 <X>421 â¾ <Suspense>422 <C key=\\"c\\">423 <B key=\\"b\\">424 <A key=\\"a\\">425 <Y>",426 "[root]427 â¾ <Root>428 <X>429 â¾ <Suspense>430 <C key=\\"c\\">431 <A key=\\"a\\">432 <Y>",433 "[root]434 â¾ <Root>435 <X>436 â¾ <Suspense>437 <C key=\\"c\\">438 <A key=\\"a\\">439 <Y>",440 "[root]441 â¾ <Root>442 <X>443 â¾ <Suspense>444 <C key=\\"c\\">445 <A key=\\"a\\">446 <Y>",447 "[root]448 â¾ <Root>449 <X>450 â¾ <Suspense>451 <A key=\\"a\\">452 <B key=\\"b\\">453 <Y>",454 "[root]455 â¾ <Root>456 <X>457 â¾ <Suspense>458 <A key=\\"a\\">459 <Y>",460 "[root]461 â¾ <Root>462 <X>463 <Suspense>464 <Y>",465 "[root]466 â¾ <Root>467 <X>468 â¾ <Suspense>469 <B key=\\"b\\">470 <Y>",471 "[root]472 â¾ <Root>473 <X>474 â¾ <Suspense>475 <A key=\\"a\\">476 <Y>",477 ]478 `);479 // 2. Verify check Suspense can render same steps as initial fallback content.480 for (let i = 0; i < steps.length; i++) {481 act(() =>482 root.render(483 <Root>484 <X />485 <React.Suspense fallback={steps[i]}>486 <Z />487 <Never />488 <Z />489 </React.Suspense>490 <Y />491 </Root>,492 ),493 );494 expect(print(store)).toEqual(snapshots[i]);495 act(() => root.unmount());496 expect(print(store)).toBe('');497 }498 // 3. Verify we can update from each step to each step in primary mode.499 for (let i = 0; i < steps.length; i++) {500 for (let j = 0; j < steps.length; j++) {501 // Always start with a fresh container and steps[i].502 container = document.createElement('div');503 // $FlowFixMe504 root = ReactDOM.createRoot(container);505 act(() =>506 root.render(507 <Root>508 <X />509 <React.Suspense fallback={z}>{steps[i]}</React.Suspense>510 <Y />511 </Root>,512 ),513 );514 expect(print(store)).toEqual(snapshots[i]);515 // Re-render with steps[j].516 act(() =>517 root.render(518 <Root>519 <X />520 <React.Suspense fallback={z}>{steps[j]}</React.Suspense>521 <Y />522 </Root>,523 ),524 );525 // Verify the successful transition to steps[j].526 expect(print(store)).toEqual(snapshots[j]);527 // Check that we can transition back again.528 act(() =>529 root.render(530 <Root>531 <X />532 <React.Suspense fallback={z}>{steps[i]}</React.Suspense>533 <Y />534 </Root>,535 ),536 );537 expect(print(store)).toEqual(snapshots[i]);538 // Clean up after every iteration.539 act(() => root.unmount());540 expect(print(store)).toBe('');541 }542 }543 // 4. Verify we can update from each step to each step in fallback mode.544 for (let i = 0; i < steps.length; i++) {545 for (let j = 0; j < steps.length; j++) {546 // Always start with a fresh container and steps[i].547 container = document.createElement('div');548 // $FlowFixMe549 root = ReactDOM.createRoot(container);550 act(() =>551 root.render(552 <Root>553 <X />554 <React.Suspense fallback={steps[i]}>555 <Z />556 <Never />557 <Z />558 </React.Suspense>559 <Y />560 </Root>,561 ),562 );563 expect(print(store)).toEqual(snapshots[i]);564 // Re-render with steps[j].565 act(() =>566 root.render(567 <Root>568 <X />569 <React.Suspense fallback={steps[j]}>570 <Z />571 <Never />572 <Z />573 </React.Suspense>574 <Y />575 </Root>,576 ),577 );578 // Verify the successful transition to steps[j].579 expect(print(store)).toEqual(snapshots[j]);580 // Check that we can transition back again.581 act(() =>582 root.render(583 <Root>584 <X />585 <React.Suspense fallback={steps[i]}>586 <Z />587 <Never />588 <Z />589 </React.Suspense>590 <Y />591 </Root>,592 ),593 );594 expect(print(store)).toEqual(snapshots[i]);595 // Clean up after every iteration.596 act(() => root.unmount());597 expect(print(store)).toBe('');598 }599 }600 // 5. Verify we can update from each step to each step when moving primary -> fallback.601 for (let i = 0; i < steps.length; i++) {602 for (let j = 0; j < steps.length; j++) {603 // Always start with a fresh container and steps[i].604 container = document.createElement('div');605 // $FlowFixMe606 root = ReactDOM.createRoot(container);607 act(() =>608 root.render(609 <Root>610 <X />611 <React.Suspense fallback={z}>{steps[i]}</React.Suspense>612 <Y />613 </Root>,614 ),615 );616 expect(print(store)).toEqual(snapshots[i]);617 // Re-render with steps[j].618 act(() =>619 root.render(620 <Root>621 <X />622 <React.Suspense fallback={steps[j]}>623 <Z />624 <Never />625 <Z />626 </React.Suspense>627 <Y />628 </Root>,629 ),630 );631 // Verify the successful transition to steps[j].632 expect(print(store)).toEqual(snapshots[j]);633 // Check that we can transition back again.634 act(() =>635 root.render(636 <Root>637 <X />638 <React.Suspense fallback={z}>{steps[i]}</React.Suspense>639 <Y />640 </Root>,641 ),642 );643 expect(print(store)).toEqual(snapshots[i]);644 // Clean up after every iteration.645 act(() => root.unmount());646 expect(print(store)).toBe('');647 }648 }649 // 6. Verify we can update from each step to each step when moving fallback -> primary.650 for (let i = 0; i < steps.length; i++) {651 for (let j = 0; j < steps.length; j++) {652 // Always start with a fresh container and steps[i].653 container = document.createElement('div');654 // $FlowFixMe655 root = ReactDOM.createRoot(container);656 act(() =>657 root.render(658 <Root>659 <X />660 <React.Suspense fallback={steps[i]}>661 <Z />662 <Never />663 <Z />664 </React.Suspense>665 <Y />666 </Root>,667 ),668 );669 expect(print(store)).toEqual(snapshots[i]);670 // Re-render with steps[j].671 act(() =>672 root.render(673 <Root>674 <X />675 <React.Suspense fallback={z}>{steps[j]}</React.Suspense>676 <Y />677 </Root>,678 ),679 );680 // Verify the successful transition to steps[j].681 expect(print(store)).toEqual(snapshots[j]);682 // Check that we can transition back again.683 act(() =>684 root.render(685 <Root>686 <X />687 <React.Suspense fallback={steps[i]}>688 <Z />689 <Never />690 <Z />691 </React.Suspense>692 <Y />693 </Root>,694 ),695 );696 expect(print(store)).toEqual(snapshots[i]);697 // Clean up after every iteration.698 act(() => root.unmount());699 expect(print(store)).toBe('');700 }701 }702 // 7. Verify we can update from each step to each step when toggling Suspense.703 for (let i = 0; i < steps.length; i++) {704 for (let j = 0; j < steps.length; j++) {705 // Always start with a fresh container and steps[i].706 container = document.createElement('div');707 // $FlowFixMe708 root = ReactDOM.createRoot(container);709 act(() =>710 root.render(711 <Root>712 <X />713 <React.Suspense fallback={steps[j]}>{steps[i]}</React.Suspense>714 <Y />715 </Root>,716 ),717 );718 // We get ID from the index in the tree above:719 // Root, X, Suspense, ...720 // ^ (index is 2)721 const suspenseID = store.getElementIDAtIndex(2);722 // Force fallback.723 expect(print(store)).toEqual(snapshots[i]);724 await actAsync(async () => {725 bridge.send('overrideSuspense', {726 id: suspenseID,727 rendererID: store.getRendererIDForElement(suspenseID),728 forceFallback: true,729 });730 });731 expect(print(store)).toEqual(snapshots[j]);732 // Stop forcing fallback.733 await actAsync(async () => {734 bridge.send('overrideSuspense', {735 id: suspenseID,736 rendererID: store.getRendererIDForElement(suspenseID),737 forceFallback: false,738 });739 });740 expect(print(store)).toEqual(snapshots[i]);741 // Trigger actual fallback.742 act(() =>743 root.render(744 <Root>745 <X />746 <React.Suspense fallback={steps[j]}>747 <Z />748 <Never />749 <Z />750 </React.Suspense>751 <Y />752 </Root>,753 ),754 );755 expect(print(store)).toEqual(snapshots[j]);756 // Force fallback while we're in fallback mode.757 act(() => {758 bridge.send('overrideSuspense', {759 id: suspenseID,760 rendererID: store.getRendererIDForElement(suspenseID),761 forceFallback: true,762 });763 });764 // Keep seeing fallback content.765 expect(print(store)).toEqual(snapshots[j]);766 // Switch to primary mode.767 act(() =>768 root.render(769 <Root>770 <X />771 <React.Suspense fallback={steps[j]}>{steps[i]}</React.Suspense>772 <Y />773 </Root>,774 ),775 );776 // Fallback is still forced though.777 expect(print(store)).toEqual(snapshots[j]);778 // Stop forcing fallback. This reverts to primary content.779 await actAsync(async () => {780 bridge.send('overrideSuspense', {781 id: suspenseID,782 rendererID: store.getRendererIDForElement(suspenseID),783 forceFallback: false,784 });785 });786 // Now we see primary content.787 expect(print(store)).toEqual(snapshots[i]);788 // Clean up after every iteration.789 await actAsync(async () => root.unmount());790 expect(print(store)).toBe('');791 }792 }793 });794 it('should handle a stress test for Suspense without type change (Concurrent Mode)', async () => {795 const A = () => 'a';796 const B = () => 'b';797 const C = () => 'c';798 const X = () => 'x';799 const Y = () => 'y';800 const Z = () => 'z';801 const a = <A key="a" />;802 const b = <B key="b" />;803 const c = <C key="c" />;804 const z = <Z key="z" />;805 // prettier-ignore806 const steps = [807 a,808 [a],809 [a, b, c],810 [c, b, a],811 [c, null, a],812 <React.Fragment>{c}{a}</React.Fragment>,813 <div>{c}{a}</div>,814 <div><span>{a}</span>{b}</div>,815 [[a]],816 null,817 b,818 a,819 ];820 const Never = () => {821 throw new Promise(() => {});822 };823 const MaybeSuspend = ({children, suspend}) => {824 if (suspend) {825 return (826 <div>827 {children}828 <Never />829 <X />830 </div>831 );832 }833 return (834 <div>835 {children}836 <Z />837 </div>838 );839 };840 const Root = ({children}) => {841 return children;842 };843 // 1. For each step, check Suspense can render them as initial primary content.844 // This is the only step where we use Jest snapshots.845 const snapshots = [];846 let container = document.createElement('div');847 // $FlowFixMe848 let root = ReactDOM.createRoot(container);849 for (let i = 0; i < steps.length; i++) {850 act(() =>851 root.render(852 <Root>853 <X />854 <React.Suspense fallback={z}>855 <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>856 </React.Suspense>857 <Y />858 </Root>,859 ),860 );861 // We snapshot each step once so it doesn't regress.862 snapshots.push(print(store));863 act(() => root.unmount());864 expect(print(store)).toBe('');865 }866 // 2. Verify check Suspense can render same steps as initial fallback content.867 // We don't actually assert here because the tree includes <MaybeSuspend>868 // which is different from the snapshots above. So we take more snapshots.869 const fallbackSnapshots = [];870 for (let i = 0; i < steps.length; i++) {871 act(() =>872 root.render(873 <Root>874 <X />875 <React.Suspense fallback={steps[i]}>876 <Z />877 <MaybeSuspend suspend={true}>{steps[i]}</MaybeSuspend>878 <Z />879 </React.Suspense>880 <Y />881 </Root>,882 ),883 );884 // We snapshot each step once so it doesn't regress.885 fallbackSnapshots.push(print(store));886 act(() => root.unmount());887 expect(print(store)).toBe('');888 }889 expect(snapshots).toMatchInlineSnapshot(`890 Array [891 "[root]892 â¾ <Root>893 <X>894 â¾ <Suspense>895 â¾ <MaybeSuspend>896 <A key=\\"a\\">897 <Z>898 <Y>",899 "[root]900 â¾ <Root>901 <X>902 â¾ <Suspense>903 â¾ <MaybeSuspend>904 <A key=\\"a\\">905 <Z>906 <Y>",907 "[root]908 â¾ <Root>909 <X>910 â¾ <Suspense>911 â¾ <MaybeSuspend>912 <A key=\\"a\\">913 <B key=\\"b\\">914 <C key=\\"c\\">915 <Z>916 <Y>",917 "[root]918 â¾ <Root>919 <X>920 â¾ <Suspense>921 â¾ <MaybeSuspend>922 <C key=\\"c\\">923 <B key=\\"b\\">924 <A key=\\"a\\">925 <Z>926 <Y>",927 "[root]928 â¾ <Root>929 <X>930 â¾ <Suspense>931 â¾ <MaybeSuspend>932 <C key=\\"c\\">933 <A key=\\"a\\">934 <Z>935 <Y>",936 "[root]937 â¾ <Root>938 <X>939 â¾ <Suspense>940 â¾ <MaybeSuspend>941 <C key=\\"c\\">942 <A key=\\"a\\">943 <Z>944 <Y>",945 "[root]946 â¾ <Root>947 <X>948 â¾ <Suspense>949 â¾ <MaybeSuspend>950 <C key=\\"c\\">951 <A key=\\"a\\">952 <Z>953 <Y>",954 "[root]955 â¾ <Root>956 <X>957 â¾ <Suspense>958 â¾ <MaybeSuspend>959 <A key=\\"a\\">960 <B key=\\"b\\">961 <Z>962 <Y>",963 "[root]964 â¾ <Root>965 <X>966 â¾ <Suspense>967 â¾ <MaybeSuspend>968 <A key=\\"a\\">969 <Z>970 <Y>",971 "[root]972 â¾ <Root>973 <X>974 â¾ <Suspense>975 â¾ <MaybeSuspend>976 <Z>977 <Y>",978 "[root]979 â¾ <Root>980 <X>981 â¾ <Suspense>982 â¾ <MaybeSuspend>983 <B key=\\"b\\">984 <Z>985 <Y>",986 "[root]987 â¾ <Root>988 <X>989 â¾ <Suspense>990 â¾ <MaybeSuspend>991 <A key=\\"a\\">992 <Z>993 <Y>",994 ]995 `);996 // 3. Verify we can update from each step to each step in primary mode.997 for (let i = 0; i < steps.length; i++) {998 for (let j = 0; j < steps.length; j++) {999 // Always start with a fresh container and steps[i].1000 container = document.createElement('div');1001 // $FlowFixMe1002 root = ReactDOM.createRoot(container);1003 act(() =>1004 root.render(1005 <Root>1006 <X />1007 <React.Suspense fallback={z}>1008 <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>1009 </React.Suspense>1010 <Y />1011 </Root>,1012 ),1013 );1014 expect(print(store)).toEqual(snapshots[i]);1015 // Re-render with steps[j].1016 act(() =>1017 root.render(1018 <Root>1019 <X />1020 <React.Suspense fallback={z}>1021 <MaybeSuspend suspend={false}>{steps[j]}</MaybeSuspend>1022 </React.Suspense>1023 <Y />1024 </Root>,1025 ),1026 );1027 // Verify the successful transition to steps[j].1028 expect(print(store)).toEqual(snapshots[j]);1029 // Check that we can transition back again.1030 act(() =>1031 root.render(1032 <Root>1033 <X />1034 <React.Suspense fallback={z}>1035 <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>1036 </React.Suspense>1037 <Y />1038 </Root>,1039 ),1040 );1041 expect(print(store)).toEqual(snapshots[i]);1042 // Clean up after every iteration.1043 act(() => root.unmount());1044 expect(print(store)).toBe('');1045 }1046 }1047 // 4. Verify we can update from each step to each step in fallback mode.1048 for (let i = 0; i < steps.length; i++) {1049 for (let j = 0; j < steps.length; j++) {1050 // Always start with a fresh container and steps[i].1051 container = document.createElement('div');1052 // $FlowFixMe1053 root = ReactDOM.createRoot(container);1054 act(() =>1055 root.render(1056 <Root>1057 <X />1058 <React.Suspense fallback={steps[i]}>1059 <Z />1060 <MaybeSuspend suspend={true}>1061 <X />1062 <Y />1063 </MaybeSuspend>1064 <Z />1065 </React.Suspense>1066 <Y />1067 </Root>,1068 ),1069 );1070 expect(print(store)).toEqual(fallbackSnapshots[i]);1071 // Re-render with steps[j].1072 act(() =>1073 root.render(1074 <Root>1075 <X />1076 <React.Suspense fallback={steps[j]}>1077 <Z />1078 <MaybeSuspend suspend={true}>1079 <Y />1080 <X />1081 </MaybeSuspend>1082 <Z />1083 </React.Suspense>1084 <Y />1085 </Root>,1086 ),1087 );1088 // Verify the successful transition to steps[j].1089 expect(print(store)).toEqual(fallbackSnapshots[j]);1090 // Check that we can transition back again.1091 act(() =>1092 root.render(1093 <Root>1094 <X />1095 <React.Suspense fallback={steps[i]}>1096 <Z />1097 <MaybeSuspend suspend={true}>1098 <X />1099 <Y />1100 </MaybeSuspend>1101 <Z />1102 </React.Suspense>1103 <Y />1104 </Root>,1105 ),1106 );1107 expect(print(store)).toEqual(fallbackSnapshots[i]);1108 // Clean up after every iteration.1109 act(() => root.unmount());1110 expect(print(store)).toBe('');1111 }1112 }1113 // 5. Verify we can update from each step to each step when moving primary -> fallback.1114 for (let i = 0; i < steps.length; i++) {1115 for (let j = 0; j < steps.length; j++) {1116 // Always start with a fresh container and steps[i].1117 container = document.createElement('div');1118 // $FlowFixMe1119 root = ReactDOM.createRoot(container);1120 act(() =>1121 root.render(1122 <Root>1123 <X />1124 <React.Suspense fallback={z}>1125 <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>1126 </React.Suspense>1127 <Y />1128 </Root>,1129 ),1130 );1131 expect(print(store)).toEqual(snapshots[i]);1132 // Re-render with steps[j].1133 act(() =>1134 root.render(1135 <Root>1136 <X />1137 <React.Suspense fallback={steps[j]}>1138 <MaybeSuspend suspend={true}>{steps[i]}</MaybeSuspend>1139 </React.Suspense>1140 <Y />1141 </Root>,1142 ),1143 );1144 // Verify the successful transition to steps[j].1145 expect(print(store)).toEqual(fallbackSnapshots[j]);1146 // Check that we can transition back again.1147 act(() =>1148 root.render(1149 <Root>1150 <X />1151 <React.Suspense fallback={z}>1152 <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>1153 </React.Suspense>1154 <Y />1155 </Root>,1156 ),1157 );1158 expect(print(store)).toEqual(snapshots[i]);1159 // Clean up after every iteration.1160 act(() => root.unmount());1161 expect(print(store)).toBe('');1162 }1163 }1164 // 6. Verify we can update from each step to each step when moving fallback -> primary.1165 for (let i = 0; i < steps.length; i++) {1166 for (let j = 0; j < steps.length; j++) {1167 // Always start with a fresh container and steps[i].1168 container = document.createElement('div');1169 // $FlowFixMe1170 root = ReactDOM.createRoot(container);1171 act(() =>1172 root.render(1173 <Root>1174 <X />1175 <React.Suspense fallback={steps[i]}>1176 <MaybeSuspend suspend={true}>{steps[j]}</MaybeSuspend>1177 </React.Suspense>1178 <Y />1179 </Root>,1180 ),1181 );1182 expect(print(store)).toEqual(fallbackSnapshots[i]);1183 // Re-render with steps[j].1184 act(() =>1185 root.render(1186 <Root>1187 <X />1188 <React.Suspense fallback={steps[i]}>1189 <MaybeSuspend suspend={false}>{steps[j]}</MaybeSuspend>1190 </React.Suspense>1191 <Y />1192 </Root>,1193 ),1194 );1195 // Verify the successful transition to steps[j].1196 expect(print(store)).toEqual(snapshots[j]);1197 // Check that we can transition back again.1198 act(() =>1199 root.render(1200 <Root>1201 <X />1202 <React.Suspense fallback={steps[i]}>1203 <MaybeSuspend suspend={true}>{steps[j]}</MaybeSuspend>1204 </React.Suspense>1205 <Y />1206 </Root>,1207 ),1208 );1209 expect(print(store)).toEqual(fallbackSnapshots[i]);1210 // Clean up after every iteration.1211 act(() => root.unmount());1212 expect(print(store)).toBe('');1213 }1214 }1215 // 7. Verify we can update from each step to each step when toggling Suspense.1216 for (let i = 0; i < steps.length; i++) {1217 for (let j = 0; j < steps.length; j++) {1218 // Always start with a fresh container and steps[i].1219 container = document.createElement('div');1220 // $FlowFixMe1221 root = ReactDOM.createRoot(container);1222 act(() =>1223 root.render(1224 <Root>1225 <X />1226 <React.Suspense fallback={steps[j]}>1227 <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>1228 </React.Suspense>1229 <Y />1230 </Root>,1231 ),1232 );1233 // We get ID from the index in the tree above:1234 // Root, X, Suspense, ...1235 // ^ (index is 2)1236 const suspenseID = store.getElementIDAtIndex(2);1237 // Force fallback.1238 expect(print(store)).toEqual(snapshots[i]);1239 await actAsync(async () => {1240 bridge.send('overrideSuspense', {1241 id: suspenseID,1242 rendererID: store.getRendererIDForElement(suspenseID),1243 forceFallback: true,1244 });1245 });1246 expect(print(store)).toEqual(fallbackSnapshots[j]);1247 // Stop forcing fallback.1248 await actAsync(async () => {1249 bridge.send('overrideSuspense', {1250 id: suspenseID,1251 rendererID: store.getRendererIDForElement(suspenseID),1252 forceFallback: false,1253 });1254 });1255 expect(print(store)).toEqual(snapshots[i]);1256 // Trigger actual fallback.1257 act(() =>1258 root.render(1259 <Root>1260 <X />1261 <React.Suspense fallback={steps[j]}>1262 <MaybeSuspend suspend={true}>{steps[i]}</MaybeSuspend>1263 </React.Suspense>1264 <Y />1265 </Root>,1266 ),1267 );1268 expect(print(store)).toEqual(fallbackSnapshots[j]);1269 // Force fallback while we're in fallback mode.1270 act(() => {1271 bridge.send('overrideSuspense', {1272 id: suspenseID,1273 rendererID: store.getRendererIDForElement(suspenseID),1274 forceFallback: true,1275 });1276 });1277 // Keep seeing fallback content.1278 expect(print(store)).toEqual(fallbackSnapshots[j]);1279 // Switch to primary mode.1280 act(() =>1281 root.render(1282 <Root>1283 <X />1284 <React.Suspense fallback={steps[j]}>1285 <MaybeSuspend suspend={false}>{steps[i]}</MaybeSuspend>1286 </React.Suspense>1287 <Y />1288 </Root>,1289 ),1290 );1291 // Fallback is still forced though.1292 expect(print(store)).toEqual(fallbackSnapshots[j]);1293 // Stop forcing fallback. This reverts to primary content.1294 await actAsync(async () => {1295 bridge.send('overrideSuspense', {1296 id: suspenseID,1297 rendererID: store.getRendererIDForElement(suspenseID),1298 forceFallback: false,1299 });1300 });1301 // Now we see primary content.1302 expect(print(store)).toEqual(snapshots[i]);1303 // Clean up after every iteration.1304 act(() => root.unmount());1305 expect(print(store)).toBe('');1306 }1307 }1308 });...
DependencyGraph-test.js
Source:DependencyGraph-test.js
1'use strict';2jest3 .dontMock('../index')4 .dontMock('q')5 .dontMock('path')6 .dontMock('absolute-path')7 .dontMock('../docblock')8 .setMock('../../../ModuleDescriptor', function(data) {return data;});9describe('DependencyGraph', function() {10 var DependencyGraph;11 var fileWatcher;12 var fs;13 beforeEach(function() {14 fs = require('fs');15 DependencyGraph = require('../index');16 fileWatcher = {17 on: function() {18 return this;19 }20 };21 });22 describe('getOrderedDependencies', function() {23 pit('should get dependencies', function() {24 var root = '/root';25 fs.__setMockFilesystem({26 'root': {27 'index.js': [28 '/**',29 ' * @providesModule index',30 ' */',31 'require("a")'32 ].join('\n'),33 'a.js': [34 '/**',35 ' * @providesModule a',36 ' */',37 ].join('\n'),38 }39 });40 var dgraph = new DependencyGraph({41 roots: [root],42 fileWatcher: fileWatcher43 });44 return dgraph.load().then(function() {45 expect(dgraph.getOrderedDependencies('/root/index.js'))46 .toEqual([47 {id: 'index', path: '/root/index.js', dependencies: ['a']},48 {id: 'a', path: '/root/a.js', dependencies: []},49 ]);50 });51 });52 pit('should get dependencies', function() {53 var root = '/root';54 fs.__setMockFilesystem({55 'root': {56 'index.js': [57 '/**',58 ' * @providesModule index',59 ' */',60 'require("image!a")'61 ].join('\n'),62 'imgs': {63 'a.png': ''64 },65 }66 });67 var dgraph = new DependencyGraph({68 roots: [root],69 fileWatcher: fileWatcher,70 assetRoots: ['/root/imgs']71 });72 return dgraph.load().then(function() {73 expect(dgraph.getOrderedDependencies('/root/index.js'))74 .toEqual([75 {id: 'index', path: '/root/index.js', dependencies: ['image!a']},76 { id: 'image!a',77 path: '/root/imgs/a.png',78 dependencies: [],79 isAsset: true80 },81 ]);82 });83 });84 pit('should get recursive dependencies', function() {85 var root = '/root';86 fs.__setMockFilesystem({87 'root': {88 'index.js': [89 '/**',90 ' * @providesModule index',91 ' */',92 'require("a")',93 ].join('\n'),94 'a.js': [95 '/**',96 ' * @providesModule a',97 ' */',98 'require("index")',99 ].join('\n'),100 }101 });102 var dgraph = new DependencyGraph({103 roots: [root],104 fileWatcher: fileWatcher105 });106 return dgraph.load().then(function() {107 expect(dgraph.getOrderedDependencies('/root/index.js'))108 .toEqual([109 {id: 'index', path: '/root/index.js', dependencies: ['a']},110 {id: 'a', path: '/root/a.js', dependencies: ['index']},111 ]);112 });113 });114 pit('should work with packages', function() {115 var root = '/root';116 fs.__setMockFilesystem({117 'root': {118 'index.js': [119 '/**',120 ' * @providesModule index',121 ' */',122 'require("aPackage")',123 ].join('\n'),124 'aPackage': {125 'package.json': JSON.stringify({126 name: 'aPackage',127 main: 'main.js'128 }),129 'main.js': 'lol'130 }131 }132 });133 var dgraph = new DependencyGraph({134 roots: [root],135 fileWatcher: fileWatcher136 });137 return dgraph.load().then(function() {138 expect(dgraph.getOrderedDependencies('/root/index.js'))139 .toEqual([140 {id: 'index', path: '/root/index.js', dependencies: ['aPackage']},141 { id: 'aPackage/main',142 path: '/root/aPackage/main.js',143 dependencies: []144 },145 ]);146 });147 });148 pit('should ignore malformed packages', function() {149 var root = '/root';150 fs.__setMockFilesystem({151 'root': {152 'index.js': [153 '/**',154 ' * @providesModule index',155 ' */',156 'require("aPackage")',157 ].join('\n'),158 'aPackage': {159 'package.json': 'lol',160 'main.js': 'lol'161 }162 }163 });164 var dgraph = new DependencyGraph({165 roots: [root],166 fileWatcher: fileWatcher167 });168 return dgraph.load().then(function() {169 expect(dgraph.getOrderedDependencies('/root/index.js'))170 .toEqual([171 {id: 'index', path: '/root/index.js', dependencies: ['aPackage']},172 ]);173 });174 });175 pit('can have multiple modules with the same name', function() {176 var root = '/root';177 fs.__setMockFilesystem({178 'root': {179 'index.js': [180 '/**',181 ' * @providesModule index',182 ' */',183 'require("b")',184 ].join('\n'),185 'b.js': [186 '/**',187 ' * @providesModule b',188 ' */',189 ].join('\n'),190 'c.js': [191 '/**',192 ' * @providesModule c',193 ' */',194 ].join('\n'),195 'somedir': {196 'somefile.js': [197 '/**',198 ' * @providesModule index',199 ' */',200 'require("c")',201 ].join('\n')202 }203 }204 });205 var dgraph = new DependencyGraph({206 roots: [root],207 fileWatcher: fileWatcher208 });209 return dgraph.load().then(function() {210 expect(dgraph.getOrderedDependencies('/root/somedir/somefile.js'))211 .toEqual([212 { id: 'index',213 path: '/root/somedir/somefile.js',214 dependencies: ['c']215 },216 { id: 'c',217 path: '/root/c.js',218 dependencies: []219 },220 ]);221 });222 });223 pit('providesModule wins when conflict with package', function() {224 var root = '/root';225 fs.__setMockFilesystem({226 'root': {227 'index.js': [228 '/**',229 ' * @providesModule index',230 ' */',231 'require("aPackage")',232 ].join('\n'),233 'b.js': [234 '/**',235 ' * @providesModule aPackage',236 ' */',237 ].join('\n'),238 'aPackage': {239 'package.json': JSON.stringify({240 name: 'aPackage',241 main: 'main.js'242 }),243 'main.js': 'lol'244 }245 }246 });247 var dgraph = new DependencyGraph({248 roots: [root],249 fileWatcher: fileWatcher250 });251 return dgraph.load().then(function() {252 expect(dgraph.getOrderedDependencies('/root/index.js'))253 .toEqual([254 { id: 'index',255 path: '/root/index.js',256 dependencies: ['aPackage']257 },258 { id: 'aPackage',259 path: '/root/b.js',260 dependencies: []261 },262 ]);263 });264 });265 pit('should be forgiving with missing requires', function() {266 var root = '/root';267 fs.__setMockFilesystem({268 'root': {269 'index.js': [270 '/**',271 ' * @providesModule index',272 ' */',273 'require("lolomg")',274 ].join('\n')275 }276 });277 var dgraph = new DependencyGraph({278 roots: [root],279 fileWatcher: fileWatcher280 });281 return dgraph.load().then(function() {282 expect(dgraph.getOrderedDependencies('/root/index.js'))283 .toEqual([284 { id: 'index',285 path: '/root/index.js',286 dependencies: ['lolomg']287 }288 ]);289 });290 });291 pit('should work with packages with subdirs', function() {292 var root = '/root';293 fs.__setMockFilesystem({294 'root': {295 'index.js': [296 '/**',297 ' * @providesModule index',298 ' */',299 'require("aPackage/subdir/lolynot")',300 ].join('\n'),301 'aPackage': {302 'package.json': JSON.stringify({303 name: 'aPackage',304 main: 'main.js'305 }),306 'main.js': 'lol',307 'subdir': {308 'lolynot.js': 'lolynot'309 }310 }311 }312 });313 var dgraph = new DependencyGraph({314 roots: [root],315 fileWatcher: fileWatcher316 });317 return dgraph.load().then(function() {318 expect(dgraph.getOrderedDependencies('/root/index.js'))319 .toEqual([320 { id: 'index',321 path: '/root/index.js',322 dependencies: ['aPackage/subdir/lolynot']323 },324 { id: 'aPackage/subdir/lolynot',325 path: '/root/aPackage/subdir/lolynot.js',326 dependencies: []327 },328 ]);329 });330 });331 pit('should work with packages with symlinked subdirs', function() {332 var root = '/root';333 fs.__setMockFilesystem({334 'symlinkedPackage': {335 'package.json': JSON.stringify({336 name: 'aPackage',337 main: 'main.js'338 }),339 'main.js': 'lol',340 'subdir': {341 'lolynot.js': 'lolynot'342 }343 },344 'root': {345 'index.js': [346 '/**',347 ' * @providesModule index',348 ' */',349 'require("aPackage/subdir/lolynot")',350 ].join('\n'),351 'aPackage': { SYMLINK: '/symlinkedPackage' },352 }353 });354 var dgraph = new DependencyGraph({355 roots: [root],356 fileWatcher: fileWatcher357 });358 return dgraph.load().then(function() {359 expect(dgraph.getOrderedDependencies('/root/index.js'))360 .toEqual([361 { id: 'index',362 path: '/root/index.js',363 dependencies: ['aPackage/subdir/lolynot']364 },365 { id: 'aPackage/subdir/lolynot',366 path: '/symlinkedPackage/subdir/lolynot.js',367 dependencies: []368 },369 ]);370 });371 });372 pit('should work with relative modules in packages', function() {373 var root = '/root';374 fs.__setMockFilesystem({375 'root': {376 'index.js': [377 '/**',378 ' * @providesModule index',379 ' */',380 'require("aPackage")',381 ].join('\n'),382 'aPackage': {383 'package.json': JSON.stringify({384 name: 'aPackage',385 main: 'main.js'386 }),387 'main.js': 'require("./subdir/lolynot")',388 'subdir': {389 'lolynot.js': 'require("../other")'390 },391 'other.js': 'some code'392 }393 }394 });395 var dgraph = new DependencyGraph({396 roots: [root],397 fileWatcher: fileWatcher398 });399 return dgraph.load().then(function() {400 expect(dgraph.getOrderedDependencies('/root/index.js'))401 .toEqual([402 { id: 'index',403 path: '/root/index.js',404 dependencies: ['aPackage']405 },406 { id: 'aPackage/main',407 path: '/root/aPackage/main.js',408 dependencies: ['./subdir/lolynot']409 },410 { id: 'aPackage/subdir/lolynot',411 path: '/root/aPackage/subdir/lolynot.js',412 dependencies: ['../other']413 },414 { id: 'aPackage/other',415 path: '/root/aPackage/other.js',416 dependencies: []417 },418 ]);419 });420 });421 });422 describe('file watch updating', function() {423 var triggerFileChange;424 beforeEach(function() {425 fileWatcher = {426 on: function(eventType, callback) {427 if (eventType !== 'all') {428 throw new Error('Can only handle "all" event in watcher.');429 }430 triggerFileChange = callback;431 return this;432 }433 };434 });435 pit('updates module dependencies', function() {436 var root = '/root';437 var filesystem = fs.__setMockFilesystem({438 'root': {439 'index.js': [440 '/**',441 ' * @providesModule index',442 ' */',443 'require("aPackage")',444 'require("foo")'445 ].join('\n'),446 'foo': [447 '/**',448 ' * @providesModule foo',449 ' */',450 'require("aPackage")'451 ].join('\n'),452 'aPackage': {453 'package.json': JSON.stringify({454 name: 'aPackage',455 main: 'main.js'456 }),457 'main.js': 'main',458 }459 }460 });461 var dgraph = new DependencyGraph({462 roots: [root],463 fileWatcher: fileWatcher464 });465 return dgraph.load().then(function() {466 filesystem.root['index.js'] =467 filesystem.root['index.js'].replace('require("foo")', '');468 triggerFileChange('change', 'index.js', root);469 return dgraph.load().then(function() {470 expect(dgraph.getOrderedDependencies('/root/index.js'))471 .toEqual([472 { id: 'index',473 path: '/root/index.js',474 dependencies: ['aPackage']475 },476 { id: 'aPackage/main',477 path: '/root/aPackage/main.js',478 dependencies: []479 },480 ]);481 });482 });483 });484 pit('updates module dependencies on file change', function() {485 var root = '/root';486 var filesystem = fs.__setMockFilesystem({487 'root': {488 'index.js': [489 '/**',490 ' * @providesModule index',491 ' */',492 'require("aPackage")',493 'require("foo")'494 ].join('\n'),495 'foo.js': [496 '/**',497 ' * @providesModule foo',498 ' */',499 'require("aPackage")'500 ].join('\n'),501 'aPackage': {502 'package.json': JSON.stringify({503 name: 'aPackage',504 main: 'main.js'505 }),506 'main.js': 'main',507 }508 }509 });510 var dgraph = new DependencyGraph({511 roots: [root],512 fileWatcher: fileWatcher513 });514 return dgraph.load().then(function() {515 filesystem.root['index.js'] =516 filesystem.root['index.js'].replace('require("foo")', '');517 triggerFileChange('change', 'index.js', root);518 return dgraph.load().then(function() {519 expect(dgraph.getOrderedDependencies('/root/index.js'))520 .toEqual([521 { id: 'index',522 path: '/root/index.js',523 dependencies: ['aPackage']524 },525 { id: 'aPackage/main',526 path: '/root/aPackage/main.js',527 dependencies: []528 },529 ]);530 });531 });532 });533 pit('updates module dependencies on file delete', function() {534 var root = '/root';535 var filesystem = fs.__setMockFilesystem({536 'root': {537 'index.js': [538 '/**',539 ' * @providesModule index',540 ' */',541 'require("aPackage")',542 'require("foo")'543 ].join('\n'),544 'foo.js': [545 '/**',546 ' * @providesModule foo',547 ' */',548 'require("aPackage")'549 ].join('\n'),550 'aPackage': {551 'package.json': JSON.stringify({552 name: 'aPackage',553 main: 'main.js'554 }),555 'main.js': 'main',556 }557 }558 });559 var dgraph = new DependencyGraph({560 roots: [root],561 fileWatcher: fileWatcher562 });563 return dgraph.load().then(function() {564 delete filesystem.root.foo;565 triggerFileChange('delete', 'foo.js', root);566 return dgraph.load().then(function() {567 expect(dgraph.getOrderedDependencies('/root/index.js'))568 .toEqual([569 { id: 'index',570 path: '/root/index.js',571 dependencies: ['aPackage', 'foo']572 },573 { id: 'aPackage/main',574 path: '/root/aPackage/main.js',575 dependencies: []576 },577 ]);578 });579 });580 });581 pit('updates module dependencies on file add', function() {582 var root = '/root';583 var filesystem = fs.__setMockFilesystem({584 'root': {585 'index.js': [586 '/**',587 ' * @providesModule index',588 ' */',589 'require("aPackage")',590 'require("foo")'591 ].join('\n'),592 'foo.js': [593 '/**',594 ' * @providesModule foo',595 ' */',596 'require("aPackage")'597 ].join('\n'),598 'aPackage': {599 'package.json': JSON.stringify({600 name: 'aPackage',601 main: 'main.js'602 }),603 'main.js': 'main',604 }605 }606 });607 var dgraph = new DependencyGraph({608 roots: [root],609 fileWatcher: fileWatcher610 });611 return dgraph.load().then(function() {612 filesystem.root['bar.js'] = [613 '/**',614 ' * @providesModule bar',615 ' */',616 'require("foo")'617 ].join('\n');618 triggerFileChange('add', 'bar.js', root);619 filesystem.root.aPackage['main.js'] = 'require("bar")';620 triggerFileChange('change', 'aPackage/main.js', root);621 return dgraph.load().then(function() {622 expect(dgraph.getOrderedDependencies('/root/index.js'))623 .toEqual([624 { id: 'index',625 path: '/root/index.js',626 dependencies: ['aPackage', 'foo']627 },628 { id: 'aPackage/main',629 path: '/root/aPackage/main.js',630 dependencies: ['bar']631 },632 { id: 'bar',633 path: '/root/bar.js',634 dependencies: ['foo']635 },636 { id: 'foo',637 path: '/root/foo.js',638 dependencies: ['aPackage']639 },640 ]);641 });642 });643 });644 pit('runs changes through ignore filter', function() {645 var root = '/root';646 var filesystem = fs.__setMockFilesystem({647 'root': {648 'index.js': [649 '/**',650 ' * @providesModule index',651 ' */',652 'require("aPackage")',653 'require("foo")'654 ].join('\n'),655 'foo.js': [656 '/**',657 ' * @providesModule foo',658 ' */',659 'require("aPackage")'660 ].join('\n'),661 'aPackage': {662 'package.json': JSON.stringify({663 name: 'aPackage',664 main: 'main.js'665 }),666 'main.js': 'main',667 }668 }669 });670 var dgraph = new DependencyGraph({671 roots: [root],672 fileWatcher: fileWatcher,673 ignoreFilePath: function(filePath) {674 if (filePath === '/root/bar.js') {675 return true;676 }677 return false;678 }679 });680 return dgraph.load().then(function() {681 filesystem.root['bar.js'] = [682 '/**',683 ' * @providesModule bar',684 ' */',685 'require("foo")'686 ].join('\n');687 triggerFileChange('add', 'bar.js', root);688 filesystem.root.aPackage['main.js'] = 'require("bar")';689 triggerFileChange('change', 'aPackage/main.js', root);690 return dgraph.load().then(function() {691 expect(dgraph.getOrderedDependencies('/root/index.js'))692 .toEqual([693 { id: 'index',694 path: '/root/index.js',695 dependencies: ['aPackage', 'foo']696 },697 { id: 'aPackage/main',698 path: '/root/aPackage/main.js',699 dependencies: ['bar']700 },701 { id: 'foo',702 path: '/root/foo.js',703 dependencies: ['aPackage']704 },705 ]);706 });707 });708 });709 pit('should ignore directory updates', function() {710 var root = '/root';711 fs.__setMockFilesystem({712 'root': {713 'index.js': [714 '/**',715 ' * @providesModule index',716 ' */',717 'require("aPackage")',718 'require("foo")'719 ].join('\n'),720 'foo.js': [721 '/**',722 ' * @providesModule foo',723 ' */',724 'require("aPackage")'725 ].join('\n'),726 'aPackage': {727 'package.json': JSON.stringify({728 name: 'aPackage',729 main: 'main.js'730 }),731 'main.js': 'main',732 }733 }734 });735 var dgraph = new DependencyGraph({736 roots: [root],737 fileWatcher: fileWatcher738 });739 return dgraph.load().then(function() {740 triggerFileChange('change', 'aPackage', '/root', {741 isDirectory: function(){ return true; }742 });743 return dgraph.load().then(function() {744 expect(dgraph.getOrderedDependencies('/root/index.js'))745 .toEqual([746 { id: 'index',747 path: '/root/index.js',748 dependencies: ['aPackage', 'foo']749 },750 { id: 'aPackage/main',751 path: '/root/aPackage/main.js',752 dependencies: []753 },754 { id: 'foo',755 path: '/root/foo.js',756 dependencies: ['aPackage']757 },758 ]);759 });760 });761 });762 });...
Node.js
Source:Node.js
1module("tinymce.html.Node");2test('construction', function() {3 var node;4 expect(15);5 node = new tinymce.html.Node('#text', 3);6 equal(node.name, '#text');7 equal(node.type, 3);8 node = new tinymce.html.Node('#comment', 8);9 equal(node.name, '#comment');10 equal(node.type, 8);11 node = new tinymce.html.Node('b', 1);12 equal(node.name, 'b');13 equal(node.type, 1);14 deepEqual(node.attributes, []);15 node = new tinymce.html.Node('#pi', 7);16 equal(node.name, '#pi');17 equal(node.type, 7);18 node = new tinymce.html.Node('#doctype', 10);19 equal(node.name, '#doctype');20 equal(node.type, 10);21 node = new tinymce.html.Node('#cdata', 4);22 equal(node.name, '#cdata');23 equal(node.type, 4);24 node = new tinymce.html.Node('#frag', 11);25 equal(node.name, '#frag');26 equal(node.type, 11);27});28test('append inside empty node', function() {29 var root, node;30 expect(10);31 root = new tinymce.html.Node('#frag', 11);32 node = root.append(new tinymce.html.Node('b', 1));33 ok(root.firstChild.parent === root);34 equal(root.firstChild.next, undefined);35 equal(root.firstChild.prev, undefined);36 equal(root.firstChild.firstChild, undefined);37 equal(root.firstChild.lastChild, undefined);38 ok(node.parent === root);39 equal(node.next, undefined);40 equal(node.prev, undefined);41 equal(node.firstChild, undefined);42 equal(node.lastChild, undefined);43});44test('append node after node', function() {45 var root, node, node2;46 expect(17);47 root = new tinymce.html.Node('#frag', 11);48 node2 = root.append(new tinymce.html.Node('a', 1));49 node = root.append(new tinymce.html.Node('b', 1));50 ok(root.firstChild.parent === root, 'root.firstChild.parent === root');51 ok(root.firstChild === node2, 'root.firstChild');52 ok(root.lastChild === node, 'root.firstChild');53 ok(root.firstChild.next === node, 'root.firstChild.next');54 equal(root.firstChild.prev, undefined, 'root.firstChild.prev');55 equal(root.firstChild.firstChild, undefined, 'root.firstChild.firstChild');56 equal(root.firstChild.lastChild, undefined, 'root.firstChild.lastChild');57 ok(node2.parent === root, 'node2.parent === root');58 ok(node2.next === node, 'node2.next');59 equal(node2.prev, undefined, 'node2.prev');60 equal(node2.firstChild, undefined, 'node2.firstChild');61 equal(node2.lastChild, undefined, 'node2.lastChild');62 ok(node.parent === root, 'node.parent === root');63 equal(node.next, undefined, 'node.next');64 ok(node.prev === node2, 'node.prev');65 equal(node.firstChild, undefined, 'node.firstChild');66 equal(node.lastChild, undefined, 'node.lastChild');67});68test('append existing node before other existing node', function() {69 var root, node, node2;70 expect(8);71 root = new tinymce.html.Node('#frag', 11);72 node = root.append(new tinymce.html.Node('a', 1));73 node2 = root.append(new tinymce.html.Node('b', 1));74 root.append(node);75 ok(root.firstChild === node2, 'root.firstChild');76 ok(root.lastChild === node, 'root.lastChild');77 equal(node.next, undefined, 'node.next');78 ok(node.prev === node2, 'node.prev');79 ok(node.parent === root, 'node.parent');80 ok(node2.parent === root, 'node2.parent');81 equal(node2.prev, undefined, 'node2.prev');82 ok(node2.next === node, 'node2.next');83});84test('remove unattached node', function() {85 expect(1);86 ok(!new tinymce.html.Node('#text', 3).remove().parent);87});88test('remove single child', function() {89 var root, node;90 expect(6);91 root = new tinymce.html.Node('#frag', 11);92 node = root.append(new tinymce.html.Node('p', 1));93 node = root.firstChild.remove();94 equal(root.firstChild, undefined);95 equal(root.lastChild, undefined);96 equal(node.parent, undefined);97 equal(node.next, undefined);98 equal(node.prev, undefined);99 equal(node.name, 'p');100});101test('remove middle node', function() {102 var root, node, node2, node3;103 expect(9);104 root = new tinymce.html.Node('#frag', 11);105 node = root.append(new tinymce.html.Node('a', 1));106 node2 = root.append(new tinymce.html.Node('b', 1));107 node3 = root.append(new tinymce.html.Node('c', 1));108 node2.remove();109 equal(node2.parent, undefined);110 equal(node2.next, undefined);111 equal(node2.prev, undefined);112 ok(root.firstChild === node, 'root.firstChild');113 ok(root.lastChild === node3, 'root.lastChild');114 ok(node.next === node3, 'node.next');115 equal(node.prev, undefined, 'node.prev');116 ok(node3.prev, node, 'node3.prev');117 equal(node3.next, undefined, 'node3.next');118});119test('insert after last', function() {120 var fragment, root, node, node2;121 expect(5);122 fragment = new tinymce.html.Node('#frag', 11);123 root = fragment.append(new tinymce.html.Node('body', 1));124 node = root.append(new tinymce.html.Node('a', 1));125 node2 = root.insert(new tinymce.html.Node('x', 1), node);126 ok(root.firstChild === node, 'root.firstChild');127 ok(root.lastChild === node2, 'root.lastChild');128 ok(node.next === node2, 'node.next');129 ok(node2.prev === node, 'node2.prev');130 ok(node2.parent === root, 'node3.next');131});132test('insert before first', function() {133 var fragment, root, node, node2;134 expect(8);135 fragment = new tinymce.html.Node('#frag', 11);136 root = fragment.append(new tinymce.html.Node('body', 1));137 node = root.append(new tinymce.html.Node('a', 1));138 node2 = root.insert(new tinymce.html.Node('x', 1), node, true);139 ok(root.firstChild === node2, 'root.firstChild');140 ok(root.lastChild === node, 'root.lastChild');141 ok(node2.parent === root, 'node2.lastChild');142 ok(node2.next === node, 'node2.next');143 ok(node2.prev === undefined, 'node2.prev');144 ok(node.parent === root, 'node.lastChild');145 ok(node.next === undefined, 'node.next');146 ok(node.prev === node2, 'node.prev');147});148test('insert before second', function() {149 var fragment, root, node, node2, node3;150 expect(5);151 fragment = new tinymce.html.Node('#frag', 11);152 root = fragment.append(new tinymce.html.Node('body', 1));153 node = root.append(new tinymce.html.Node('a', 1));154 node2 = root.append(new tinymce.html.Node('b', 1));155 node3 = root.insert(new tinymce.html.Node('x', 1), node2, true);156 ok(root.firstChild === node, 'root.firstChild');157 ok(root.lastChild === node2, 'root.lastChild');158 ok(node3.parent === root, 'node3.parent');159 ok(node3.next === node2, 'node3.next');160 ok(node3.prev === node, 'node3.prev');161});162test('insert after and between two nodes', function() {163 var root, node, node2, node3, fragment;164 expect(7);165 fragment = new tinymce.html.Node('#frag', 11);166 root = fragment.append(new tinymce.html.Node('body', 1));167 node = root.append(new tinymce.html.Node('a', 1));168 node2 = root.append(new tinymce.html.Node('b', 1));169 node3 = root.insert(new tinymce.html.Node('x', 1), node);170 ok(root.firstChild === node, 'root.firstChild');171 ok(root.lastChild === node2, 'root.lastChild');172 ok(node.next === node3, 'node.next');173 ok(node2.prev === node3, 'node2.prev');174 ok(node3.parent === root, 'node3.next');175 ok(node3.next === node2, 'node3.next');176 ok(node3.prev === node, 'node3.prev');177});178test('replace single child', function() {179 var root, node1, node2;180 expect(5);181 root = new tinymce.html.Node('#frag', 11);182 node1 = root.append(new tinymce.html.Node('b', 1));183 node2 = root.append(new tinymce.html.Node('em', 1));184 node1.replace(node2);185 ok(root.firstChild === node2, 'root.firstChild');186 ok(root.lastChild === node2, 'root.lastChild');187 ok(node2.parent === root, 'node2.parent');188 ok(!node2.next, 'node2.next');189 ok(!node2.prev, 'node2.prev');190});191test('replace first child', function() {192 var root, node1, node2, node3;193 expect(5);194 root = new tinymce.html.Node('#frag', 11);195 node1 = root.append(new tinymce.html.Node('b', 1));196 node2 = root.append(new tinymce.html.Node('em', 1));197 node3 = root.append(new tinymce.html.Node('b', 1));198 node1.replace(node2);199 ok(root.firstChild === node2, 'root.firstChild');200 ok(root.lastChild === node3, 'root.lastChild');201 ok(node2.parent === root, 'node2.parent');202 ok(node2.next === node3, 'node2.next');203 ok(!node2.prev, 'node2.prev');204});205test('replace last child', function() {206 var root, node1, node2, node3;207 expect(5);208 root = new tinymce.html.Node('#frag', 11);209 node1 = root.append(new tinymce.html.Node('b', 1));210 node3 = root.append(new tinymce.html.Node('b', 1));211 node2 = root.append(new tinymce.html.Node('em', 1));212 node3.replace(node2);213 ok(root.firstChild === node1, 'root.firstChild');214 ok(root.lastChild === node2, 'root.lastChild');215 ok(node2.parent === root, 'node2.parent');216 ok(!node2.next, 'node2.next');217 ok(node2.prev === node1, 'node2.prev');218});219test('replace middle child', function() {220 var root, node1, node2, node3, node4;221 expect(5);222 root = new tinymce.html.Node('#frag', 11);223 node1 = root.append(new tinymce.html.Node('b', 1));224 node2 = root.append(new tinymce.html.Node('b', 1));225 node3 = root.append(new tinymce.html.Node('b', 1));226 node4 = root.append(new tinymce.html.Node('em', 1));227 node2.replace(node4);228 ok(root.firstChild === node1, 'root.firstChild');229 ok(root.lastChild === node3, 'root.lastChild');230 ok(node4.parent === root, 'node4.parent');231 ok(node4.next === node3, 'node4.next');232 ok(node4.prev === node1, 'node4.prev');233});234test('attr', 22, function() {235 var node;236 node = new tinymce.html.Node('b', 1);237 deepEqual(node.attributes, []);238 node.attr('attr1', 'value1');239 equal(node.attr('attr1'), 'value1');240 equal(node.attr('attr2'), undefined);241 deepEqual(node.attributes, [{name: 'attr1', value: 'value1'}]);242 deepEqual(node.attributes.map, {'attr1': 'value1'});243 node = new tinymce.html.Node('b', 1);244 deepEqual(node.attributes, []);245 node.attr('attr1', 'value1');246 node.attr('attr1', 'valueX');247 equal(node.attr('attr1'), 'valueX');248 deepEqual(node.attributes, [{name: 'attr1', value: 'valueX'}]);249 deepEqual(node.attributes.map, {'attr1': 'valueX'});250 node = new tinymce.html.Node('b', 1);251 deepEqual(node.attributes, []);252 node.attr('attr1', 'value1');253 node.attr('attr2', 'value2');254 equal(node.attr('attr1'), 'value1');255 equal(node.attr('attr2'), 'value2');256 deepEqual(node.attributes, [{name: 'attr1', value: 'value1'}, {name: 'attr2', value: 'value2'}]);257 deepEqual(node.attributes.map, {'attr1': 'value1', 'attr2': 'value2'});258 node = new tinymce.html.Node('b', 1);259 deepEqual(node.attributes, []);260 node.attr('attr1', 'value1');261 node.attr('attr1', null);262 equal(node.attr('attr1'), undefined);263 deepEqual(node.attributes, []);264 deepEqual(node.attributes.map, {});265 node = new tinymce.html.Node('b', 1);266 node.attr({a:'1', b:'2'});267 deepEqual(node.attributes, [{name: 'a', value: '1'}, {name: 'b', value: '2'}]);268 deepEqual(node.attributes.map, {a:'1', b:'2'});269 node = new tinymce.html.Node('b', 1);270 node.attr(null);271 deepEqual(node.attributes, []);272 deepEqual(node.attributes.map, {});273});274test('clone', function() {275 var root, node, clone;276 expect(16);277 node = new tinymce.html.Node('#text', 3);278 node.value = 'value';279 clone = node.clone();280 equal(clone.name, '#text');281 equal(clone.type, 3);282 equal(clone.value, 'value');283 equal(clone.parent, undefined);284 equal(clone.next, undefined);285 equal(clone.prev, undefined);286 root = new tinymce.html.Node('#frag', 11);287 node = new tinymce.html.Node('#text', 3);288 node.value = 'value';289 root.append(node);290 equal(clone.name, '#text');291 equal(clone.type, 3);292 equal(clone.value, 'value');293 equal(clone.parent, undefined);294 equal(clone.next, undefined);295 equal(clone.prev, undefined);296 node = new tinymce.html.Node('b', 1);297 node.attr('id', 'id');298 node.attr('class', 'class');299 node.attr('title', 'title');300 clone = node.clone();301 equal(clone.name, 'b');302 equal(clone.type, 1);303 deepEqual(clone.attributes, [{name: 'class', value: 'class'}, {name: 'title', value: 'title'}]);304 deepEqual(clone.attributes.map, {'class': 'class', 'title': 'title'});305});306test('unwrap', function() {307 var root, node1, node2, node3;308 expect(7);309 root = new tinymce.html.Node('#frag', 11);310 node1 = root.append(new tinymce.html.Node('b', 1));311 node2 = node1.append(new tinymce.html.Node('em', 1));312 node1.unwrap();313 ok(root.firstChild === node2, 'root.firstChild');314 ok(root.lastChild === node2, 'root.lastChild');315 ok(node2.parent === root, 'node2.parent');316 root = new tinymce.html.Node('#frag', 11);317 node1 = root.append(new tinymce.html.Node('b', 1));318 node2 = node1.append(new tinymce.html.Node('em', 1));319 node3 = node1.append(new tinymce.html.Node('span', 1));320 node1.unwrap();321 ok(root.firstChild === node2, 'root.firstChild');322 ok(root.lastChild === node3, 'root.lastChild');323 ok(node2.parent === root, 'node2.parent');324 ok(node3.parent === root, 'node3.parent');325});326test('empty', function() {327 var root, node1, node2;328 expect(4);329 root = new tinymce.html.Node('#frag', 11);330 node1 = root.append(new tinymce.html.Node('b', 1));331 node2 = node1.append(new tinymce.html.Node('em', 1));332 node1.empty();333 ok(root.firstChild === node1, 'root.firstChild');334 ok(root.lastChild === node1, 'root.firstChild');335 ok(!node1.firstChild, 'node1.firstChild');336 ok(!node1.lastChild, 'node1.firstChild');337});338test('isEmpty', function() {339 var root, node1, node2;340 expect(9);341 root = new tinymce.html.Node('#frag', 11);342 node1 = root.append(new tinymce.html.Node('p', 1));343 node2 = node1.append(new tinymce.html.Node('b', 1));344 ok(root.isEmpty({img: 1}), 'Is empty 1');345 ok(node1.isEmpty({img: 1}), 'Is empty 2');346 root = new tinymce.html.Node('#frag', 11);347 node1 = root.append(new tinymce.html.Node('p', 1));348 node2 = node1.append(new tinymce.html.Node('img', 1));349 ok(!root.isEmpty({img: 1}), 'Is not empty 1');350 ok(!node1.isEmpty({img: 1}), 'Is not empty 2');351 root = new tinymce.html.Node('#frag', 11);352 node1 = root.append(new tinymce.html.Node('p', 1));353 node2 = node1.append(new tinymce.html.Node('#text', 3));354 node2.value = 'X';355 ok(!root.isEmpty({img: 1}), 'Is not empty 3');356 ok(!node1.isEmpty({img: 1}), 'Is not empty 4');357 root = new tinymce.html.Node('#frag', 11);358 node1 = root.append(new tinymce.html.Node('p', 1));359 node2 = node1.append(new tinymce.html.Node('#text', 3));360 node2.value = '';361 ok(root.isEmpty({img: 1}), 'Is empty 4');362 ok(node1.isEmpty({img: 1}), 'Is empty 5');363 root = new tinymce.html.Node('#frag', 11);364 node1 = root.append(new tinymce.html.Node('a', 1)).attr('name', 'x');365 ok(!root.isEmpty({img: 1}), 'Contains anchor with name attribute.');...
CaretBookmark.js
Source:CaretBookmark.js
1ModuleLoader.require([2 'tinymce/caret/CaretBookmark',3 'tinymce/caret/CaretPosition'4], function(CaretBookmark, CaretPosition) {5 var assertCaretPosition = Utils.assertCaretPosition;6 module('tinymce.caret.CaretBookmark');7 function getRoot() {8 return document.getElementById('view');9 }10 function setupHtml(html) {11 getRoot().innerHTML = html;12 }13 function createTextPos(textNode, offset) {14 return new CaretPosition(textNode, offset);15 }16 test('create element index', function() {17 setupHtml('<b></b><i></i><b></b>');18 equal(CaretBookmark.create(getRoot(), CaretPosition.before(getRoot().childNodes[0])), 'b[0],before');19 equal(CaretBookmark.create(getRoot(), CaretPosition.before(getRoot().childNodes[1])), 'i[0],before');20 equal(CaretBookmark.create(getRoot(), CaretPosition.before(getRoot().childNodes[2])), 'b[1],before');21 equal(CaretBookmark.create(getRoot(), CaretPosition.after(getRoot().childNodes[2])), 'b[1],after');22 });23 test('create text index', function() {24 setupHtml('a<b></b>b<b></b>ccc');25 equal(CaretBookmark.create(getRoot(), createTextPos(getRoot().childNodes[0], 0)), 'text()[0],0');26 equal(CaretBookmark.create(getRoot(), createTextPos(getRoot().childNodes[2], 1)), 'text()[1],1');27 equal(CaretBookmark.create(getRoot(), createTextPos(getRoot().childNodes[4], 3)), 'text()[2],3');28 });29 test('create text index on fragmented text nodes', function() {30 setupHtml('a');31 getRoot().appendChild(document.createTextNode('b'));32 getRoot().appendChild(document.createTextNode('c'));33 getRoot().appendChild(document.createElement('b'));34 getRoot().appendChild(document.createTextNode('d'));35 getRoot().appendChild(document.createTextNode('e'));36 equal(getRoot().childNodes.length, 6);37 equal(CaretBookmark.create(getRoot(), createTextPos(getRoot().childNodes[0], 0)), 'text()[0],0');38 equal(CaretBookmark.create(getRoot(), createTextPos(getRoot().childNodes[1], 0)), 'text()[0],1');39 equal(CaretBookmark.create(getRoot(), createTextPos(getRoot().childNodes[2], 0)), 'text()[0],2');40 equal(CaretBookmark.create(getRoot(), createTextPos(getRoot().childNodes[4], 0)), 'text()[1],0');41 equal(CaretBookmark.create(getRoot(), createTextPos(getRoot().childNodes[5], 0)), 'text()[1],1');42 });43 test('create br element index', function() {44 setupHtml('<p><br data-mce-bogus="1"></p><p><br></p>');45 equal(CaretBookmark.create(getRoot(), CaretPosition.before(getRoot().firstChild.firstChild)), 'p[0]/br[0],before');46 equal(CaretBookmark.create(getRoot(), CaretPosition.before(getRoot().lastChild.firstChild)), 'p[1]/br[0],before');47 });48 test('create deep element index', function() {49 setupHtml('<p><span>a</span><span><b id="a"></b><b id="b"></b><b id="c"></b></span></p>');50 equal(CaretBookmark.create(getRoot(), CaretPosition.before(document.getElementById('a'))), 'p[0]/span[1]/b[0],before');51 equal(CaretBookmark.create(getRoot(), CaretPosition.before(document.getElementById('b'))), 'p[0]/span[1]/b[1],before');52 equal(CaretBookmark.create(getRoot(), CaretPosition.before(document.getElementById('c'))), 'p[0]/span[1]/b[2],before');53 equal(CaretBookmark.create(getRoot(), CaretPosition.after(document.getElementById('c'))), 'p[0]/span[1]/b[2],after');54 });55 test('create deep text index', function() {56 setupHtml('<p><span>a</span><span id="x">a<b></b>b<b></b>ccc</span></p>');57 equal(CaretBookmark.create(getRoot(), createTextPos(document.getElementById('x').childNodes[0], 0)), 'p[0]/span[1]/text()[0],0');58 equal(CaretBookmark.create(getRoot(), createTextPos(document.getElementById('x').childNodes[2], 1)), 'p[0]/span[1]/text()[1],1');59 equal(CaretBookmark.create(getRoot(), createTextPos(document.getElementById('x').childNodes[4], 3)), 'p[0]/span[1]/text()[2],3');60 });61 test('create element index from bogus', function() {62 setupHtml('<b></b><span data-mce-bogus="1"><b></b><span data-mce-bogus="1"><b></b><b></b></span></span>');63 equal(CaretBookmark.create(getRoot(), CaretPosition.before(getRoot().lastChild.lastChild.childNodes[1])), 'b[3],before');64 });65 test('resolve element index', function() {66 setupHtml('<b></b><i></i><b></b>');67 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'b[0],before'), CaretPosition.before(getRoot().childNodes[0]));68 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'b[1],before'), CaretPosition.before(getRoot().childNodes[2]));69 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'b[1],after'), CaretPosition.after(getRoot().childNodes[2]));70 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'i[0],before'), CaretPosition.before(getRoot().childNodes[1]));71 });72 test('resolve odd element names', function() {73 setupHtml('<h-2X>abc</h-2X>');74 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'h-2X[0]/text()[0],2'), createTextPos(getRoot().childNodes[0].firstChild, 2));75 });76 test('resolve deep element index', function() {77 setupHtml('<p><span>a</span><span><b id="a"></b><b id="b"></b><b id="c"></b></span></p>');78 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'p[0]/span[1]/b[0],before'), CaretPosition.before(document.getElementById('a')));79 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'p[0]/span[1]/b[1],before'), CaretPosition.before(document.getElementById('b')));80 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'p[0]/span[1]/b[2],before'), CaretPosition.before(document.getElementById('c')));81 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'p[0]/span[1]/b[2],after'), CaretPosition.after(document.getElementById('c')));82 });83 test('resolve text index', function() {84 setupHtml('a<b></b>b<b></b>ccc');85 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'text()[0],0'), createTextPos(getRoot().childNodes[0], 0));86 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'text()[1],1'), createTextPos(getRoot().childNodes[2], 1));87 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'text()[2],3'), createTextPos(getRoot().childNodes[4], 3));88 });89 test('resolve text index on fragmented text nodes', function() {90 setupHtml('a');91 getRoot().appendChild(document.createTextNode('b'));92 getRoot().appendChild(document.createTextNode('c'));93 getRoot().appendChild(document.createElement('b'));94 getRoot().appendChild(document.createTextNode('d'));95 getRoot().appendChild(document.createTextNode('e'));96 equal(getRoot().childNodes.length, 6);97 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'text()[0],0'), createTextPos(getRoot().childNodes[0], 0));98 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'text()[0],1'), createTextPos(getRoot().childNodes[0], 1));99 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'text()[0],2'), createTextPos(getRoot().childNodes[1], 1));100 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'text()[0],3'), createTextPos(getRoot().childNodes[2], 1));101 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'text()[0],4'), createTextPos(getRoot().childNodes[2], 1));102 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'text()[1],0'), createTextPos(getRoot().childNodes[4], 0));103 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'text()[1],1'), createTextPos(getRoot().childNodes[4], 1));104 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'text()[1],2'), createTextPos(getRoot().childNodes[5], 1));105 });106 test('resolve text index with to high offset', function() {107 setupHtml('abc');108 assertCaretPosition(CaretBookmark.resolve(getRoot(), 'text()[0],10'), createTextPos(getRoot().childNodes[0], 3));109 });110 test('resolve invalid paths', function() {111 setupHtml('<b><i></i></b>');112 equal(CaretBookmark.resolve(getRoot(), 'x[0]/y[1]/z[2]'), null);113 equal(CaretBookmark.resolve(getRoot(), 'b[0]/i[2]'), null);114 equal(CaretBookmark.resolve(getRoot(), 'x'), null);115 equal(CaretBookmark.resolve(getRoot(), null), null);116 });...
rootattributeoperation.js
Source:rootattributeoperation.js
1/**2 * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.3 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license4 */5import Model from '../../../src/model/model';6import DocumentFragment from '../../../src/model/documentfragment';7import Element from '../../../src/model/element';8import RootAttributeOperation from '../../../src/model/operation/rootattributeoperation';9import { expectToThrowCKEditorError } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';10describe( 'RootAttributeOperation', () => {11 let model, doc, root;12 beforeEach( () => {13 model = new Model();14 doc = model.document;15 root = doc.createRoot();16 } );17 describe( 'type', () => {18 it( 'should be addRootAttribute for adding attribute', () => {19 const op = new RootAttributeOperation(20 root,21 'key',22 null,23 'newValue',24 doc.version25 );26 expect( op.type ).to.equal( 'addRootAttribute' );27 } );28 it( 'should be removeRootAttribute for removing attribute', () => {29 const op = new RootAttributeOperation(30 root,31 'key',32 'oldValue',33 null,34 doc.version35 );36 expect( op.type ).to.equal( 'removeRootAttribute' );37 } );38 it( 'should be changeRootAttribute for removing attribute', () => {39 const op = new RootAttributeOperation(40 root,41 'key',42 'oldValue',43 'newValue',44 doc.version45 );46 expect( op.type ).to.equal( 'changeRootAttribute' );47 } );48 } );49 it( 'should add attribute on the root element', () => {50 model.applyOperation(51 new RootAttributeOperation(52 root,53 'isNew',54 null,55 true,56 doc.version57 )58 );59 expect( doc.version ).to.equal( 1 );60 expect( root.hasAttribute( 'isNew' ) ).to.be.true;61 } );62 it( 'should change attribute on the root element', () => {63 root._setAttribute( 'isNew', false );64 model.applyOperation(65 new RootAttributeOperation(66 root,67 'isNew',68 false,69 true,70 doc.version71 )72 );73 expect( doc.version ).to.equal( 1 );74 expect( root.getAttribute( 'isNew' ) ).to.be.true;75 } );76 it( 'should remove attribute from the root element', () => {77 root._setAttribute( 'x', true );78 model.applyOperation(79 new RootAttributeOperation(80 root,81 'x',82 true,83 null,84 doc.version85 )86 );87 expect( doc.version ).to.equal( 1 );88 expect( root.hasAttribute( 'x' ) ).to.be.false;89 } );90 it( 'should create a RootAttributeOperation as a reverse', () => {91 const operation = new RootAttributeOperation( root, 'x', 'old', 'new', doc.version );92 const reverse = operation.getReversed();93 expect( reverse ).to.be.an.instanceof( RootAttributeOperation );94 expect( reverse.baseVersion ).to.equal( 1 );95 expect( reverse.root ).to.equal( root );96 expect( reverse.key ).to.equal( 'x' );97 expect( reverse.oldValue ).to.equal( 'new' );98 expect( reverse.newValue ).to.equal( 'old' );99 } );100 it( 'should undo adding attribute by applying reverse operation', () => {101 const operation = new RootAttributeOperation(102 root,103 'isNew',104 null,105 true,106 doc.version107 );108 const reverse = operation.getReversed();109 model.applyOperation( operation );110 model.applyOperation( reverse );111 expect( doc.version ).to.equal( 2 );112 expect( root.hasAttribute( 'x' ) ).to.be.false;113 } );114 it( 'should undo changing attribute by applying reverse operation', () => {115 root._setAttribute( 'isNew', false );116 const operation = new RootAttributeOperation(117 root,118 'isNew',119 false,120 true,121 doc.version122 );123 const reverse = operation.getReversed();124 model.applyOperation( operation );125 model.applyOperation( reverse );126 expect( doc.version ).to.equal( 2 );127 expect( root.getAttribute( 'isNew' ) ).to.be.false;128 } );129 it( 'should undo remove attribute by applying reverse operation', () => {130 root._setAttribute( 'foo', true );131 const operation = new RootAttributeOperation(132 root,133 'foo',134 true,135 null,136 doc.version137 );138 const reverse = operation.getReversed();139 model.applyOperation( operation );140 model.applyOperation( reverse );141 expect( doc.version ).to.equal( 2 );142 expect( root.getAttribute( 'foo' ) ).to.be.true;143 } );144 describe( '_validate()', () => {145 it( 'should throw an error when trying to change non-root element', () => {146 const child = new Element( 'p' );147 const parent = new Element( 'p' );148 parent._appendChild( child );149 expectToThrowCKEditorError( () => {150 const op = new RootAttributeOperation(151 child,152 'foo',153 null,154 'bar',155 null156 );157 op._validate();158 }, /rootattribute-operation-not-a-root/ );159 } );160 it( 'should throw an error when trying to change document fragment', () => {161 expectToThrowCKEditorError( () => {162 const op = new RootAttributeOperation(163 new DocumentFragment(),164 'foo',165 null,166 'bar',167 null168 );169 op._validate();170 }, /rootattribute-operation-not-a-root/ );171 } );172 it( 'should throw an error when trying to remove an attribute that does not exists', () => {173 expectToThrowCKEditorError( () => {174 const op = new RootAttributeOperation(175 root,176 'foo',177 true,178 null,179 doc.version180 );181 op._validate();182 }, /rootattribute-operation-wrong-old-value/, model );183 } );184 it( 'should throw an error when trying to add an attribute that already exists', () => {185 root._setAttribute( 'x', 1 );186 expectToThrowCKEditorError( () => {187 const op = new RootAttributeOperation(188 root,189 'x',190 null,191 2,192 doc.version193 );194 op._validate();195 }, /rootattribute-operation-attribute-exists/, model );196 } );197 } );198 it( 'should create a RootAttributeOperation with the same parameters when cloned', () => {199 const baseVersion = doc.version;200 const op = new RootAttributeOperation( root, 'foo', 'old', 'new', baseVersion );201 const clone = op.clone();202 // New instance rather than a pointer to the old instance.203 expect( clone ).not.to.equal( op );204 expect( clone ).to.be.instanceof( RootAttributeOperation );205 expect( clone.root ).to.equal( root );206 expect( clone.key ).to.equal( 'foo' );207 expect( clone.oldValue ).to.equal( 'old' );208 expect( clone.newValue ).to.equal( 'new' );209 expect( clone.baseVersion ).to.equal( baseVersion );210 } );211 describe( 'toJSON', () => {212 it( 'should create proper serialized object', () => {213 const op = new RootAttributeOperation(214 root,215 'key',216 null,217 'newValue',218 doc.version219 );220 const serialized = op.toJSON();221 expect( serialized.__className ).to.equal( 'RootAttributeOperation' );222 expect( serialized ).to.deep.equal( {223 __className: 'RootAttributeOperation',224 baseVersion: 0,225 key: 'key',226 newValue: 'newValue',227 oldValue: null,228 root: 'main'229 } );230 } );231 } );232 describe( 'fromJSON', () => {233 it( 'should create proper RootAttributeOperation from json object', () => {234 const op = new RootAttributeOperation( root, 'key', null, 'newValue', doc.version );235 const serialized = op.toJSON();236 const deserialized = RootAttributeOperation.fromJSON( serialized, doc );237 expect( deserialized ).to.deep.equal( op );238 } );239 it( 'should throw an error when root does not exists', () => {240 const op = new RootAttributeOperation(241 root,242 'key',243 null,244 'newValue',245 doc.version246 );247 const serialized = op.toJSON();248 serialized.root = 'no-root';249 expectToThrowCKEditorError( () => {250 RootAttributeOperation.fromJSON( serialized, doc );251 }, /rootattribute-operation-fromjson-no-root/ );252 } );253 } );...
api.js
Source:api.js
1// 以ä¸æ¯ä¸å¡æå¡å¨APIå°å2// æ¬æºå¼åæ¶ä½¿ç¨3 var WxApiRoot = 'http://localhost:8080/wx/';4// å±åç½æµè¯ä½¿ç¨5// var WxApiRoot = 'http://192.168.0.101:8080/wx/';6// äºå¹³å°é¨ç½²æ¶ä½¿ç¨7// var WxApiRoot = 'http://122.152.206.172:8080/wx/';8// äºå¹³å°ä¸çº¿æ¶ä½¿ç¨9// var WxApiRoot = 'https://www.menethil.com.cn/wx/';10module.exports = {11 IndexUrl: WxApiRoot + 'home/index', //é¦é¡µæ°æ®æ¥å£12 CatalogList: WxApiRoot + 'catalog/index', //åç±»ç®å½å
¨é¨åç±»æ°æ®æ¥å£13 CatalogCurrent: WxApiRoot + 'catalog/current', //åç±»ç®å½å½ååç±»æ°æ®æ¥å£14 AuthLoginByWeixin: WxApiRoot + 'auth/login_by_weixin', //微信ç»å½15 AuthLoginByAccount: WxApiRoot + 'auth/login', //è´¦å·ç»å½16 AuthRegister: WxApiRoot + 'auth/register', //è´¦å·æ³¨å17 AuthReset: WxApiRoot + 'auth/reset', //è´¦å·å¯ç éç½®18 AuthRegisterCaptcha: WxApiRoot + 'auth/regCaptcha', //éªè¯ç 19 AuthBindPhone: WxApiRoot + 'auth/bindPhone', //ç»å®å¾®ä¿¡ææºå·20 GoodsCount: WxApiRoot + 'goods/count', //ç»è®¡ååæ»æ°21 GoodsList: WxApiRoot + 'goods/list', //è·å¾ååå表22 GoodsCategory: WxApiRoot + 'goods/category', //è·å¾åç±»æ°æ®23 GoodsDetail: WxApiRoot + 'goods/detail', //è·å¾ååç详æ
24 GoodsNew: WxApiRoot + 'goods/new', //æ°å25 GoodsHot: WxApiRoot + 'goods/hot', //çé¨26 GoodsRelated: WxApiRoot + 'goods/related', //åå详æ
页çå
³èååï¼å¤§å®¶é½å¨çï¼27 BrandList: WxApiRoot + 'brand/list', //åçå表28 BrandDetail: WxApiRoot + 'brand/detail', //åç详æ
29 CartList: WxApiRoot + 'cart/index', //è·åè´ç©è½¦çæ°æ®30 CartAdd: WxApiRoot + 'cart/add', // æ·»å ååå°è´ç©è½¦31 CartFastAdd: WxApiRoot + 'cart/fastadd', // ç«å³è´ä¹°åå32 CartUpdate: WxApiRoot + 'cart/update', // æ´æ°è´ç©è½¦çåå33 CartDelete: WxApiRoot + 'cart/delete', // å é¤è´ç©è½¦çåå34 CartChecked: WxApiRoot + 'cart/checked', // éæ©æåæ¶éæ©åå35 CartGoodsCount: WxApiRoot + 'cart/goodscount', // è·åè´ç©è½¦åå件æ°36 CartCheckout: WxApiRoot + 'cart/checkout', // ä¸ååä¿¡æ¯ç¡®è®¤37 CollectList: WxApiRoot + 'collect/list', //æ¶èå表38 CollectAddOrDelete: WxApiRoot + 'collect/addordelete', //æ·»å æåæ¶æ¶è39 CommentList: WxApiRoot + 'comment/list', //è¯è®ºå表40 CommentCount: WxApiRoot + 'comment/count', //è¯è®ºæ»æ°41 CommentPost: WxApiRoot + 'comment/post', //å表è¯è®º42 TopicList: WxApiRoot + 'topic/list', //ä¸é¢å表43 TopicDetail: WxApiRoot + 'topic/detail', //ä¸é¢è¯¦æ
44 TopicRelated: WxApiRoot + 'topic/related', //ç¸å
³ä¸é¢45 SearchIndex: WxApiRoot + 'search/index', //æç´¢å
³é®å46 SearchResult: WxApiRoot + 'search/result', //æç´¢ç»æ47 SearchHelper: WxApiRoot + 'search/helper', //æ索帮å©48 SearchClearHistory: WxApiRoot + 'search/clearhistory', //æç´¢åå²æ¸
æ¥49 AddressList: WxApiRoot + 'address/list', //æ¶è´§å°åå表50 AddressDetail: WxApiRoot + 'address/detail', //æ¶è´§å°å详æ
51 AddressSave: WxApiRoot + 'address/save', //ä¿åæ¶è´§å°å52 AddressDelete: WxApiRoot + 'address/delete', //ä¿åæ¶è´§å°å53 ExpressQuery: WxApiRoot + 'express/query', //ç©æµæ¥è¯¢54 RegionList: WxApiRoot + 'region/list', //è·ååºåå表55 OrderSubmit: WxApiRoot + 'order/submit', // æ交订å56 OrderPrepay: WxApiRoot + 'order/prepay', // 订åçé¢æ¯ä»ä¼è¯57 OrderList: WxApiRoot + 'order/list', //订åå表58 OrderDetail: WxApiRoot + 'order/detail', //订å详æ
59 OrderCancel: WxApiRoot + 'order/cancel', //åæ¶è®¢å60 OrderRefund: WxApiRoot + 'order/refund', //é款åæ¶è®¢å61 OrderDelete: WxApiRoot + 'order/delete', //å é¤è®¢å62 OrderConfirm: WxApiRoot + 'order/confirm', //确认æ¶è´§63 OrderComment: WxApiRoot + 'order/comment', // 代è¯ä»·ååä¿¡æ¯64 FootprintList: WxApiRoot + 'footprint/list', //足迹å表65 FootprintDelete: WxApiRoot + 'footprint/delete', //å é¤è¶³è¿¹66 UserFormIdCreate: WxApiRoot + 'formid/create', //ç¨æ·FromIdï¼ç¨äºåé模çæ¶æ¯67 GroupOn: WxApiRoot + 'groupon/query', //å¢è´API-æ¥è¯¢68 GroupOnMy: WxApiRoot + 'groupon/my', //å¢è´API-æçå¢è´69 GroupOnDetail: WxApiRoot + 'groupon/detail', //å¢è´API-详æ
70 GroupOnJoin: WxApiRoot + 'groupon/join', //å¢è´API-详æ
71 StorageUpload: WxApiRoot + 'storage/upload' //å¾çä¸ä¼ ...
binaryTree.js
Source:binaryTree.js
1'use strict';2class Node {3 constructor(value) {4 this.value = value;5 this.left = null;6 this.right = null;7 }8}9class BinaryTree {10 constructor() {11 this.root = null;12 }13 preOrder() {14 let resultArr = [];15 let _preOrder = (root) => {16 if (root !== null) {17 resultArr.push(root.value);18 if (root.left !== null) {19 _preOrder(root.left);20 }21 if (root.right !== null) {22 _preOrder(root.right);23 }24 }25 };26 _preOrder(this.root);27 return resultArr;28 }29 inOrder() {30 let resultArr = [];31 let _inOrder = (root) => {32 if (root !== null) {33 if (root.left !== null) {34 _inOrder(root.left);35 }36 resultArr.push(root.value);37 if (root.right !== null) {38 _inOrder(root.right);39 }40 }41 };42 _inOrder(this.root);43 return resultArr;44 }45 postOrder() {46 let resultArr = [];47 let _postOrder = (root) => {48 if (root !== null) {49 if (root.left !== null) {50 _postOrder(root.left);51 }52 if (root.right !== null) {53 _postOrder(root.right);54 }55 resultArr.push(root.value);56 }57 };58 _postOrder(this.root);59 return resultArr;60 }61 addBinarySearch(value) {62 let _add = (inputValue, root) => {63 if (root === null) {64 root = new Node(inputValue);65 }66 else if (root.value === inputValue) {67 throw `Binary Search Tree already contains ${inputValue}. Nothing was added to the tree`;68 }69 else if (inputValue < root.value) {70 root.left = _add(inputValue, root.left);71 }72 else if (inputValue > root.value) {73 root.right = _add(inputValue, root.right);74 }75 return root;76 };77 try {78 this.root = _add(value, this.root);79 } catch (error) {80 console.log(error);81 }82 }83 findMax() {84 if (this.root === null) {85 throw 'Error: Binary Tree is empty';86 }87 else {88 let max = null;89 let _preOrderMax = (root, maxValue) => {90 if (root !== null) {91 if (root.value > maxValue) {92 maxValue = root.value;93 }94 if (root.left !== null) {95 maxValue = _preOrderMax(root.left, maxValue);96 }97 if (root.right !== null) {98 maxValue = _preOrderMax(root.right, maxValue);99 }100 }101 return maxValue;102 };103 max = this.root.value;104 return _preOrderMax(this.root, max);105 }106 }107}...
rootelement.js
Source:rootelement.js
1/**2 * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.3 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license4 */5import Model from '../../src/model/model';6import Element from '../../src/model/element';7import RootElement from '../../src/model/rootelement';8import count from '@ckeditor/ckeditor5-utils/src/count';9describe( 'RootElement', () => {10 describe( 'constructor()', () => {11 it( 'should create root element without attributes', () => {12 const model = new Model();13 const doc = model.document;14 const root = new RootElement( doc );15 expect( root ).to.be.an.instanceof( Element );16 expect( root ).to.have.property( 'document' ).that.equals( doc );17 expect( count( root.getAttributes() ) ).to.equal( 0 );18 expect( root.childCount ).to.equal( 0 );19 } );20 } );21 describe( 'is()', () => {22 let root;23 before( () => {24 const model = new Model();25 const doc = model.document;26 root = new RootElement( doc, '$root' );27 } );28 it( 'should return true for rootElement, element, element with same name and element name', () => {29 expect( root.is( 'element', '$root' ) ).to.be.true;30 expect( root.is( 'model:element', '$root' ) ).to.be.true;31 expect( root.is( 'element' ) ).to.be.true;32 expect( root.is( 'model:element' ) ).to.be.true;33 expect( root.is( 'rootElement', '$root' ) ).to.be.true;34 expect( root.is( 'model:rootElement', '$root' ) ).to.be.true;35 expect( root.is( 'rootElement' ) ).to.be.true;36 expect( root.is( 'model:rootElement' ) ).to.be.true;37 expect( root.is( 'node' ) ).to.be.true;38 expect( root.is( 'model:node' ) ).to.be.true;39 } );40 it( 'should return false for other accept values', () => {41 expect( root.is( 'element', '$graveyard' ) ).to.be.false;42 expect( root.is( 'model:element', '$graveyard' ) ).to.be.false;43 expect( root.is( 'rootElement', '$graveyard' ) ).to.be.false;44 expect( root.is( 'model:rootElement', '$graveyard' ) ).to.be.false;45 expect( root.is( '$graveyard' ) ).to.be.false;46 expect( root.is( '$text' ) ).to.be.false;47 expect( root.is( '$textProxy' ) ).to.be.false;48 expect( root.is( 'documentFragment' ) ).to.be.false;49 expect( root.is( 'view:element' ) ).to.be.false;50 expect( root.is( '$root' ) ).to.be.false;51 expect( root.is( 'model:$root' ) ).to.be.false;52 expect( root.is( 'node', '$root' ) ).to.be.false;53 expect( root.is( 'model:node', '$root' ) ).to.be.false;54 } );55 } );...
Using AI Code Generation
1import { root } from 'storybook-root-decorator'2import { storiesOf } from '@storybook/react'3storiesOf('test', module)4 .addDecorator(root())5 .add('test', () => <div>test</div>)6import { configure } from '@storybook/react'7import { addDecorator } from '@storybook/react'8import { root } from 'storybook-root-decorator'9addDecorator(root())10configure(() => {11 require('../test.js')12}, module)13import { root } from 'storybook-root-decorator'14import { storiesOf } from '@storybook/react'15storiesOf('test', module)16 .addDecorator(root())17 .add('test', () => <div>test</div>)18import { configure } from '@storybook/react'19import { addDecorator } from '@storybook/react'20import { root } from 'storybook-root-decorator'21addDecorator(root())22import { withInfo } from '@storybook/addon-info'23addDecorator(withInfo())24configure(() => {25 require('../test.js')26}, module)27Usage with other decorators (with a decorator factory)28import { root } from 'storybook-root-decorator'29import { storiesOf } from '@storybook/react'30storiesOf('test', module)31 .addDecorator(root())32 .add('test', () => <div>test</div>)33import { configure } from '@storybook/react'34import { addDecorator } from '@storybook/react'35import { root } from 'storybook-root-decorator'36addDecorator(root())37import { withInfo } from '@storybook/addon-info'38addDecorator(withInfo({ inline: true }))39configure(() => {40 require('../test.js')41}, module)42Usage with other decorators (with a decorator factory and a story decorator)43import { root } from 'storybook-root-decorator'44import { storiesOf } from '@storybook/react'45storiesOf('test', module)
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!